【问题标题】:LWJGL java.awt.HeadlessException thrown when making a JFrame制作 JFrame 时抛出 LWJGL java.awt.HeadlessException
【发布时间】:2018-04-10 21:21:44
【问题描述】:

您好,我正在处理一个小组项目,代码可以在我队友的 PC 上运行,但我一直遇到 MacOS 特定的错误。而这一次我似乎被困住了(谷歌无法轻易找到答案)。

a previous post 中,我发现我需要“-Djava.awt.headless=true”作为虚拟机设置才能正确运行我的模拟。现在,当我尝试在一些 JFrame 中生成时,由于那个 VM 标志,它们都会遇到一个可爱的“java.awt.HeadlessException”异常。

努力实现

我也希望能够在我的 MacBook 上生成这些 JFrame。

问题

我需要 -Djava.awt.headless 同时为真和假,我的程序才能在 Mac 上正常运行。如果我正确理解了我的问题,则意味着我手上有一个大问题。

编辑:在我的 Macbook 上的虚拟机中运行它可以让我正确运行项目。这远非理想的解决方案。我仍在寻找解决这个晦涩问题的方法。

我尝试了什么

  • 没有使用 VM 选项运行:出现previous post 中描述的问题。因此,这不是一个可行的选择
  • 使用 VM 选项运行:这会在创建 JFrame 时引发 -Djava.awt.headless

【问题讨论】:

  • “我需要 -Djava.awt.headless 同时为真和假,我的程序才能正常运行” 为什么需要false 状态?你说它适用于Windows。如果两者都需要truefalse,为什么它不会显示相同的问题?
  • 真正的声明需要在 Mac 上使用缓冲图像(请参阅我链接的上一篇文章)。但要生成这些 JPanel,无头模式不允许为真。编辑:所以 Windows 队友不需要有 VM 设置 -Djava.awt.headless=true 所以他们确实可以产生 JPanel。
  • 你有什么版本的 MacOS 和 Java?

标签: java macos awt lwjgl


【解决方案1】:

解决此问题的最佳方法可能是返回并以不同的方式解决您原来的问题。

您必须确保您没有在主线程(GLFW 线程)中初始化您的BufferedImage,它必须单独完成。很难从你原来的问题中分辨出来,但这似乎是那里的部分原因。启动一个新线程来进行图像处理。

请参阅此答案底部的我的解决方案和建议以获取快速摘要,并在此处查看遇到相同问题的其他人:Java Creating Instance of BufferedImage Freezes Program


简要说明为什么您的代码可以在 Windows 而不是 Mac 上运行:这是因为这两个操作系统通常运行不同的 openGL 实现,并且通常 Mac 可能会落后并错过一系列可能解决问题的更新/更改,例如这个是为了在openGL线程上初始化BufferedImage时不会冻结。


如果上述方法不起作用,那么让我们先看看什么是无头模式。 (强调我的):

完整文章和更多信息请参见底部的链接。

无头模式是一种系统配置,其中显示设备、 缺少键盘或鼠标。听起来很意外,但实际上你可以 在此模式下执行不同的操作,即使是图形数据。

在哪里适用?假设你的应用反复生成某张图片,比如一张图形授权码 每次用户登录系统时都必须更改它。什么时候 创建图像时,您的应用程序既不需要显示也不需要 键盘。 现在假设您有一台大型机或专用 没有显示设备、键盘或鼠标的项目上的服务器。 理想的决定是使用该环境的大量计算 视觉和非视觉特征的力量。 图片 在无头模式系统中生成的然后可以传递给 用于进一步渲染的 headful 系统。

那么什么时候应该使用无头模式:

在没有显示设备、键盘或鼠标的机器上。

那不是你吗?但是,如果是您(LWJGL?),那么让我们看看您如何使用无头模式:

在无头模式系统中生成的图像可以 传递给 headful 系统进行进一步渲染。

这意味着您应该有一段特殊的无头代码来处理您的无头图像,然后将图像传递回带有头部的普通 JFrame。

那么为什么它会失败:

如果显示设备、键盘或鼠标,许多组件都会受到影响 不支持。一个适当的类构造函数抛出一个 无头异常

  • 按钮
  • 复选框
  • 选择
  • 对话框
  • 文件对话框
  • 框架
  • 标签
  • 列表
  • 菜单
  • 菜单栏
  • 菜单项
  • 弹出菜单
  • 滚动条
  • 滚动窗格
  • 文本区域
  • 文本字段
  • 窗口

问题解决方法:

某些类,例如 Canvas 或 Panel,可以在无头模式下执行。

完美,所以我们只需要小心在无头模式下使用的内容。您询问了如何同时使用和不使用无头模式,而不是在需要时使用 System.setProperty("java.awt.headless", "true"); 使用 VM 选项 -Djava.awt.headless you can do it programmatically within your code 全局设置无头模式。 JFrame 应该是正常的(不是无头的),但您可以将 JPanel 生成为无头而不会出现问题。

我推荐:

您创建一个没有生成 JFrame 的 VM 选项的普通有头主线程,然后使用该主线程生成一个新的子线程并将该线程中的 LWJGL 位设置为无头,这样您就可以运行 LWJGL代码没有问题,同时您仍然可以从主线程获得 JFrame。请记住确保缓冲图像不是在主 LWJGL/OpenGL 线程中完成的。


无头信息来源: http://www.oracle.com/technetwork/articles/javase/headless-136834.html

【讨论】:

  • 感谢您的详细回答。我目前正在做一个对时间非常敏感的项目,所以我无法尝试这个。我确实认为这会解决我的问题。最具成本效益的解决方案是在我的 Mac 上双启动 Ubuntu。
  • @ArnoC 如果您不知道如何使用线程,另一个类似的答案是:分发两个 jar 文件。第一个可以是处理 JFrames 的小型普通/有头程序,第二个可以从第一个启动,它可以包含所有无头 LWJGL 代码。您可以使用 Socket 在两个 Jar 之间进行通信,或者您可以简单地将图像保存到文件并让另一个打开它。有关启动另一个 Jar 的一些信息,请参见此处:stackoverflow.com/a/27790046/1270000
  • “生成 JFrames 的 VM 选项,然后使用该主线程生成一个新的子线程并将该线程中的 LWJGL 位设置为无头”我想必须非常小心计时 /执行此操作时的同步,因为系统属性是每个 VM 的,即在线程之间共享。当您在 LWJGL 线程上设置 "java.awt.headless", "true" 时,其他线程也会看到更改后的值,如果他们当时读取它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-31
  • 2017-12-30
  • 1970-01-01
相关资源
最近更新 更多