在 Windows 台机器上使用 Java Swing SystemLookAndFeel 会导致 CachedPainter 和 JTextPanes 出现内存泄漏
Using Java Swing SystemLookAndFeel on Windows machines leads to MemoryLeaks in CachedPainter with JTextPanes
我已经为一个棘手的问题苦苦挣扎了很多天。在我的 Java Swing 应用程序中,我使用两个 JTextPane
扩展 XML-Text 的语法高亮,如本例中所述,并做了一些小改动:
XML Syntax Highlighting in JTextPanes
这两个JTextPane
放在一个JSplitPane
中的两个JScollPane
中直接放在一个JFrame
的ContentPane
中。第一个 TextPane
是可编辑的(就像一个简单的 XML-Request-Editor),第二个 TextPane
显示 XML- 来自我的服务器后端的响应。
只要我不尝试将 "many lines" 放入那些 XmlTextPane
中,一切都会按预期进行。这导致使用的内存快速增加(在向 TextPane
中的一个或两个插入几行后,内存从 < 100 MB 增加到 1,000 MB)。
奇怪的是,即使重置 TextPane
s and/or 删除它们(或处理包含 Component
s 的 Frame
)也不会改变内存完全用过!强制垃圾收集也不会改变任何东西。有些东西必须仍然持有对分配的东西的引用....
为了查看到底是什么占用了所有内存,我尝试使用 Eclipse MATS 分析应用程序,结果如下:
这清楚地表明 CachedPainter
持有很多东西...
询问 Google 似乎我不是唯一遇到 CachePainter
内存问题的人,但我找不到原因 - 更重要的是 - 和解决方案。
在纠结了好几个小时之后,我发现当我将我的应用程序设置为使用
时,这个问题不会发生
UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
而不是
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
借助跨平台外观,我能够在 TextPane
中放入数千行 XML 内容,而不会占用超过 200 MB 的内存。
使用相同的代码但设置为平台外观 (Windows 7),我在 ~200 行后达到超过 2k MB 的内存使用量
我可以针对 JDK7 和 JDK8 重现此行为:(.
是什么原因造成的,我该如何解决?
€编辑:
一些附加信息:
在进一步的研究中,似乎某些 LAF 在 d3d 缓冲区方面存在问题。 MATS 屏幕截图中的这个 int[] 可能是某种渲染缓冲区,也指向相同的可能方向....
我的应用程序已经设置了这个以防止一些渲染性能问题(例如调整帧大小!):
System.setProperty("sun.java2d.noddraw", Boolean.TRUE.toString());
我也可以尝试将此标志添加到启动参数中:
-Dsun.java2d.d3d=false
还是您认为这没有帮助?
别担心。这不是内存泄漏。
ImageCache
是基于 SoftReference
的。来自消息来源
public class ImageCache {
private int maxCount;
private final LinkedList<SoftReference<ImageCache.Entry>> entries;
....
来自 Javadoc
保证在虚拟机抛出 OutOfMemoryError
.
之前清除所有对软可达对象的软引用
所以当你没有足够的内存时,清除缓存以释放足够的内存。
我已经为一个棘手的问题苦苦挣扎了很多天。在我的 Java Swing 应用程序中,我使用两个 JTextPane
扩展 XML-Text 的语法高亮,如本例中所述,并做了一些小改动:
XML Syntax Highlighting in JTextPanes
这两个JTextPane
放在一个JSplitPane
中的两个JScollPane
中直接放在一个JFrame
的ContentPane
中。第一个 TextPane
是可编辑的(就像一个简单的 XML-Request-Editor),第二个 TextPane
显示 XML- 来自我的服务器后端的响应。
只要我不尝试将 "many lines" 放入那些 XmlTextPane
中,一切都会按预期进行。这导致使用的内存快速增加(在向 TextPane
中的一个或两个插入几行后,内存从 < 100 MB 增加到 1,000 MB)。
奇怪的是,即使重置 TextPane
s and/or 删除它们(或处理包含 Component
s 的 Frame
)也不会改变内存完全用过!强制垃圾收集也不会改变任何东西。有些东西必须仍然持有对分配的东西的引用....
为了查看到底是什么占用了所有内存,我尝试使用 Eclipse MATS 分析应用程序,结果如下:
这清楚地表明 CachedPainter
持有很多东西...
询问 Google 似乎我不是唯一遇到 CachePainter
内存问题的人,但我找不到原因 - 更重要的是 - 和解决方案。
在纠结了好几个小时之后,我发现当我将我的应用程序设置为使用
时,这个问题不会发生UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
而不是
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
借助跨平台外观,我能够在 TextPane
中放入数千行 XML 内容,而不会占用超过 200 MB 的内存。
使用相同的代码但设置为平台外观 (Windows 7),我在 ~200 行后达到超过 2k MB 的内存使用量
我可以针对 JDK7 和 JDK8 重现此行为:(.
是什么原因造成的,我该如何解决?
€编辑: 一些附加信息: 在进一步的研究中,似乎某些 LAF 在 d3d 缓冲区方面存在问题。 MATS 屏幕截图中的这个 int[] 可能是某种渲染缓冲区,也指向相同的可能方向.... 我的应用程序已经设置了这个以防止一些渲染性能问题(例如调整帧大小!):
System.setProperty("sun.java2d.noddraw", Boolean.TRUE.toString());
我也可以尝试将此标志添加到启动参数中:
-Dsun.java2d.d3d=false
还是您认为这没有帮助?
别担心。这不是内存泄漏。
ImageCache
是基于 SoftReference
的。来自消息来源
public class ImageCache {
private int maxCount;
private final LinkedList<SoftReference<ImageCache.Entry>> entries;
....
来自 Javadoc
保证在虚拟机抛出 OutOfMemoryError
.
所以当你没有足够的内存时,清除缓存以释放足够的内存。