在 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中直接放在一个JFrameContentPane中。第一个 TextPane 是可编辑的(就像一个简单的 XML-Request-Editor),第二个 TextPane 显示 XML- 来自我的服务器后端的响应。

只要我不尝试将 "many lines" 放入那些 XmlTextPane 中,一切都会按预期进行。这导致使用的内存快速增加(在向 TextPane 中的一个或两个插入几行后,内存从 < 100 MB 增加到 1,000 MB)。

奇怪的是,即使重置 TextPanes and/or 删除它们(或处理包含 Components 的 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.

之前清除所有对软可达对象的软引用

所以当你没有足够的内存时,清除缓存以释放足够的内存。