我正在编写一个利用JavaFX的应用程序,每隔20-30秒就会在屏幕上滚动大量图像内容。这意味着能够运行多个小时,提取全新内容并每隔几分钟丢弃旧内容。我的系统上有512Mb的图形内存,几分钟后,所有内存都被JavaFX占用,无论我对JavaFX场景做什么,都没有发布。当他们离开场景时我一直非常小心地丢弃节点,并且最多我一次在内存中有50-60个图像节点。我真的需要能够对支持这些图像的图形内存进行硬释放,但由于JavaFX中的Image接口看起来非常高,因此无法弄清楚如何实现这一点。 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 Add explicit access to a native resource cleanup function on nodes.
答案 0 :(得分:1)
也许您遇到与以下问题的根本原因相关的行为:
RT-16011 Need mechanism for PG nodes to know when they are no longer part of a scene graph
来自问题说明:
某些PG节点包含非堆资源的句柄,例如GPU纹理,当节点不再是场景图的一部分时,我们希望积极回收这些句柄。不幸的是,没有机制向他们报告这种状态变化,以便他们可以释放他们的资源,因此我们必须依靠GC,Ref队列的组合,有时候最终确定来回收资源。当垃圾收集落后并且我们耗尽这些有限的资源时,其中一些资源的延迟回收可能会导致异常。
当您查看我链接的问题页面时,您可以看到许多其他相关问题(需要注册才能查看问题,但任何人都可以注册)。
与样本相关的问题是:
用户评论过:
我发现我的应用程序的解决方法只是为所有经常使用的节点设置使用cashe为false。工作2天没有任何崩溃。
因此,请尝试在您的节点上调用setCache(false)。
还尝试使用Java 8 preview release修复了其中一些问题,看看它是否会提高应用程序的稳定性。虽然目前,即使在Java 8分支中,仍然存在以下未解决的问题:
RT-25323 Need a unified Texture resource management system for Prism
目前纹理资源在至少2个地方单独管理,具体取决于它的使用方式;一个是图像的纹理缓存,另一个是RTT的ImagePool。这种方法在其设计中存在缺陷,即2个高速缓存彼此不知道,并假设系统具有无限的本机资源。
使用video card with more memory 可以减少或消除问题。
您可能还希望整理一个minimal executable example来演示您的问题并提出bug request against the JavaFX Runtime project,以便JavaFX开发人员可以调查您的方案并查看它是新的还是已知问题的副本
答案 1 :(得分:1)
我能想到的最好的解决方法是将我的JVM的最大堆设置为我的显卡可用限制的一半。 (我有512mb的图形内存,所以我把它设置为-Xmx256m)这迫使GC更加主动地清理我丢弃的javafx.image.Image对象,这反过来似乎触发了JavaFX部分的图形内存清理。
以前我的堆空间设置为512mb,(我有4GB的系统内存,所以这是一个非常易于管理的限制)。问题似乎是JVM在清理我的图像时非常懒惰,直到它开始接近512mb的限制。由于我的所有图像数据都被复制到图形内存中,这意味着在JVM真正开始关注清理之前,我很可能已经耗尽了我的图形内存。
我确实尝试了jewelsea的一些建议:
我正在调用setCache(false),所以这可能会产生积极影响,但在我删除最大堆大小之前,我没有注意到改进。
我尝试使用Java8运行并获得了一些积极的结果。它确实在图形内存管理方面表现得更好,但它仍然占用了我所有的内存,并且在我差不多出来之前似乎没有开始关心图形内存。如果减少应用程序的堆限制是不可行的,那么评估Java8预发布可能是值得的。
我将向JavaFX项目发布一些功能请求,并提供指向JIRA门票的链接。