繁体   English   中英

BufferedImage.getGraphics()导致内存泄漏,是否有修复?

[英]BufferedImage.getGraphics() resulting in memory leak, is there a fix?

我遇到一些框架API调用BufferedImage.getGraphics()方法的问题,从而导致内存泄漏。 这个方法的作用是它总是调用BufferedImage.createGraphics()。 在Windows机器上,createGraphics()由Win32GraphicsEnvironment处理,它将侦听器列表保存在其字段displayChanger中 当我在BufferedImage someChart上调用getGraphics时, someChart的SurfaceManager(保留对someChart的引用)被添加到Win32GraphicsEnvironment中的侦听器映射中,从而防止someChart被垃圾收集。 之后没有任何东西从侦听器地图中删除someChart的SurfaceManager。

通常,一旦调用getGraphics,阻止BufferedImage被垃圾收集的汇总路径如下:

GC Root - > localGraphicsEnvironment(Win32GraphicsEnvironment) - > displayChanger(SunDisplayChanger) - > listeners(Map) - > key (D3DChachingSurfaceManager) - > bImg(BufferedImage)

我本可以更改框架的代码,以便在每次调用BufferedImage.getGraphics()之后,我保留对BufferedImage的SurfaceManager的引用。 然后,我获取localGraphicsEnvironment,将其强制转换为Win32GraphicsEnvironment,然后使用对BufferedImage的SurfaceManager的引用调用removeDisplayChangedListener()。 但我不认为这是解决问题的正确方法。

有人可以帮我解决这个问题吗? 非常感谢!


更多细节和发现

我试图添加到我的UI的组件每次重新绘制时都会调用BufferedImage.getGraphics()。 因此, displayChanger (在SunGraphicsEnvironment内部)保留的垃圾数量应随着组件重新绘制而增长。

然而,事情表现得非常奇怪:

当我在我的UI上计算我的操作肯定会触发重绘时,然后检查displayChanger中的垃圾监听器的数量与我的计数,它们不匹配。 (例如,在点击之前有8位听众,我点击了60次。毕竟,只有18位听众。)

另一方面,如果我打开断点,并进入向displayListeners添加内容的过程,则每次单击都会在displayListeners中生成一个新条目。 因此, displayListeners持有的每个BufferedImage 都会变成垃圾。

我认为可以共享或重用SurfaceManager作为displayListeners的键的可能性,但我的实验排除了这种可能性。 我也考虑过缓存,我故意通过每次调用重绘独特的方式来防止缓存发生。 不过,我不知道如何发生这种情况以及如何解决泄漏问题。

渲染BufferedImage ,应该在createGraphics()返回的图形上下文中调用dispose() createGraphics() 这是一个示例和类似方法的列表

附录:这似乎是一个称为包装的物体泄漏; 监听器不匹配听起来像使用调试器的工件。 您可以从Brian Goetz的文章“ 使用软引用插入内存泄漏”中获得一些想法。

当您不再需要图像时,尝试调用flush()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM