3

我正在编写一个利用 JavaFX 的应用程序,该应用程序每 20-30 秒在屏幕上滚动和关闭大量图像内容。它意味着能够运行多个小时,每隔几分钟就会引入全新的内容并丢弃旧内容。我的系统上有 512Mb 的图形内存,几分钟后,所有这些内存都被 JavaFX 消耗掉了,无论我对 JavaFX 场景做什么,它都没有被释放。当节点离开场景时,我一直非常小心地丢弃节点,一次最多在内存中有 50-60 个图像节点。我真的需要能够硬释放支持这些图像的图形内存,但无法弄清楚如何实现这一点,因为 JavaFX 中的图像接口似乎非常高级。

我正在寻找类似 java.awt.image.Image 上的 flush() 方法:http: //docs.oracle.com/javase/7/docs/api/java/awt/Image.html#flush()

我在 Linux 上运行 java 7u13。

编辑:

我设法找到了一个潜在的解决方法(见下文),但也输入了 JavaFX JIRA 票证以请求上述功能:

RT-28661 在节点上添加对本机资源清理功能的显式访问。

4

2 回答 2

1

我能想到的最佳解决方法是将 JVM 的最大堆设置为显卡可用限制的一半。(我有 512mb 的图形内存,所以我将其设置为 -Xmx256m )这迫使 GC 更主动地清理我丢弃的 javafx.image.Image 对象,这反过来似乎触发了 JavaFX 的图形内存清理.

以前我的堆空间设置为 512mb,(我有 4gb 的系统内存,所以这是一个非常易于管理的限制)。问题似乎是 JVM 非常懒惰地清理我的图像,直到它开始接近这个 512mb 的限制。由于我所有的图像数据都被复制到了图形内存中,这意味着我很可能在 JVM 真正开始真正关心清理之前已经耗尽了我的图形内存。

我确实尝试了jewelsea的一些建议:

我正在调用 setCache(false),所以这可能会产生积极的影响,但是直到我降低了最大堆大小后我才注意到改进。

我尝试使用 Java8 运行并取得了一些积极的结果。它似乎在图形内存管理方面表现得更好,但它仍然吞噬了我所有的内存,并且似乎直到我快要出局时才开始关心图形内存。如果降低应用程序的堆限制不可行,那么评估 Java8 预发行版可能是值得的。

我将向 JavaFX 项目发布一些功能请求,并将提供指向 JIRA 票证的链接。

于 2013-02-22T16:14:53.683 回答
1

也许您遇到了与以下问题的根本原因相关的行为:

RT-16011 需要让 PG 节点知道它们何时不再是场景图的一部分的机制

从问题描述:

一些 PG 节点包含非堆资源的句柄,例如 GPU 纹理,当节点不再是场景图的一部分时,我们希望积极回收这些资源。不幸的是,没有机制向他们报告这种状态变化,以便他们可以释放他们的资源,所以我们必须依靠 GC、Ref 队列和有时完成来回收资源的组合。当垃圾收集落后并且我们用完这些有限的资源时,对其中一些资源的延迟回收可能会导致异常。

当您查看我链接的问题页面时,您可以看到许多其他相关问题(需要注册才能查看问题,但任何人都可以注册)。

与示例相关的问题是:

RT-15516 与从场景中删除的缓存节点关联的图像数据未积极释放

一位用户评论说:

我为我的应用程序找到了一个解决方法,只是将所有经常使用的节点设置为使用 Cashe 为 false。工作 2 天没有任何崩溃。

因此,请尝试在您的节点上调用setCache(false) 。

还可以尝试使用已修复其中一些问题的Java 8 预览版,看看它是否提高了应用程序的稳定性。尽管目前,即使在 Java 8 分支中,仍然存在以下未解决的问题:

RT-25323 Prism 需要一个统一的纹理资源管理系统

目前纹理资源至少在两个地方单独管理,具体取决于它的使用方式;一个是图像的纹理缓存,另一个是 RTT 的 ImagePool。这种方法在其设计上存在缺陷,即 2 个缓存彼此不知道,并且假定系统具有无限的本地资源。

使用具有更多内存的视频卡 可以减少或消除该问题。

您可能还希望组合一个最小的可执行示例来演示您的问题并针对 JavaFX 运行时项目提出错误请求,以便 JavaFX 开发人员可以调查您的方案并查看它是新问题还是已知问题的重复。

于 2013-02-21T18:22:57.570 回答