有没有办法强制 JavaFX 释放视频内存?
Posted
技术标签:
【中文标题】有没有办法强制 JavaFX 释放视频内存?【英文标题】:Is there any way to force JavaFX to release video memory? 【发布时间】:2013-02-21 13:48:22 【问题描述】:我正在编写一个利用 JavaFX 的应用程序,该应用程序每隔 20-30 秒就会在屏幕上上下滚动大量图像内容。它意味着能够运行多个小时,每隔几分钟就会引入全新的内容并丢弃旧内容。我的系统上有 512Mb 的图形内存,几分钟后,所有这些内存都被 JavaFX 消耗了,无论我如何处理我的 JavaFX 场景,它都没有被释放。当节点离开场景时,我一直非常小心地丢弃节点,一次最多在内存中有 50-60 个图像节点。我真的需要能够硬释放支持这些图像的图形内存,但无法弄清楚如何实现这一点,因为 JavaFX 中的图像接口似乎非常高级。 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.
【问题讨论】:
【参考方案1】:我能想到的最佳解决方法是将 JVM 的最大堆设置为显卡可用限制的一半。 (我有 512mb 的图形内存,所以我将其设置为 -Xmx256m )这迫使 GC 更主动地清理我丢弃的 javafx.image.Image 对象,这反过来似乎触发了 JavaFX 的图形内存清理.
以前我的堆空间设置为 512mb,(我有 4gb 的系统内存,所以这是一个非常易于管理的限制)。问题似乎在于 JVM 非常懒惰地清理我的图像,直到它开始接近这个 512mb 的限制。由于我所有的图像数据都被复制到了图形内存中,这意味着我很可能在 JVM 真正开始真正关心清理之前就已经耗尽了我的图形内存。
我确实尝试了jewelsea的一些建议:
我正在调用 setCache(false),因此这可能会产生积极的影响,但直到我降低了最大堆大小后我才注意到改进。
我尝试使用 Java8 运行并取得了一些积极的结果。它似乎在图形内存管理方面表现得更好,但它仍然吞噬了我所有的内存,并且似乎直到我快要出局时才开始关心图形内存。如果降低应用程序的堆限制不可行,那么评估 Java8 预发行版可能是值得的。
我将向 JavaFX 项目发布一些功能请求,并将提供指向 JIRA 票证的链接。
【讨论】:
明确一点,“一半”没有什么神奇之处,您只需要确保为需要在系统上运行的其他任何东西留出足够的空间。 在调整和监视我的设置几天后,这种解决方法似乎只取得了一定程度的成功。如果我打开缓存,我的视频内存仍然会失控,即使关闭它,它最终也会超出我的堆空间设置。似乎 GC 实际上不足以触发原生资源清理。向 JIRA 发布票证以请求明确的清理访问权限。 RT-28661【参考方案2】:您可能遇到与以下问题的根本原因相关的行为:
RT-16011 Need mechanism for PG nodes to know when they are no longer part of a scene graph
来自问题描述:
一些 PG 节点包含非堆资源的句柄,例如 GPU 纹理,当节点不再是场景图的一部分时,我们希望积极回收这些资源。不幸的是,没有机制向他们报告这种状态变化,以便他们可以释放他们的资源,所以我们必须依靠 GC、Ref 队列和有时完成来回收资源的组合。当垃圾收集落后并且我们用完这些有限的资源时,对其中一些资源的延迟回收可能会导致异常。
当您查看我链接的问题页面时,您可以看到许多其他相关问题(需要注册才能查看问题,但任何人都可以注册)。
一个示例相关问题是:
RT-15516 image data associated with cached nodes that are removed from a scene are not aggressively released
用户评论的:
我为我的应用找到了一个解决方法,只是将所有经常使用的节点设置为使用 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 开发人员可以调查您的场景并查看它是新问题还是已知问题的重复。
【讨论】:
感谢您的彻底回复。我目前正在使用最新的 Java 8 预览版运行该应用程序,迄今为止取得了可喜的成果。它仍然会占用我的大部分图形内存,但在接近本机资源限制时释放内存似乎更好。我让我们的应用程序在一夜之间运行,然后会在早上看到系统的样子。我认为我的问题正是 RT-15516 中列出的问题。我可能仍会输入请求公开清除方法的 API 的票证。以上是关于有没有办法强制 JavaFX 释放视频内存?的主要内容,如果未能解决你的问题,请参考以下文章