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

时间:2010-06-05 13:43:56

标签: java swing memory-leaks bufferedimage

我遇到一些框架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) - >听众(地图) - > 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的键的可能性,但我的实验排除了这种可能性。我也考虑过缓存,我故意通过每次调用重绘独特的方式来防止缓存发生。不过,我不知道如何发生这种情况以及如何解决泄漏问题。

2 个答案:

答案 0 :(得分:7)

渲染BufferedImage后,您应该在createGraphics()返回的图形上下文中调用dispose()。这是类似方法的examplelist

附录:这似乎是一个名为packratting的对象泄漏;监听器不匹配听起来像使用调试器的工件。您可以从Brian Goetz的文章Plugging memory leaks with soft references中获得一些想法。

答案 1 :(得分:1)

当您不再需要图片时,尝试拨打flush()