我正在使用 jProfiler 来查找 Java Swing 应用程序中的内存泄漏。我已经确定了一个 JFrame 实例的数量不断增加。
这个窗口被打开,然后关闭。
使用 jProfiler 并查看到 GC 根路径时,只有一个引用:'JNI 全局引用'。
这是什么意思?为什么它会保留每个框架实例?
这个窗口被打开,然后关闭。
使用 jProfiler 并查看到 GC 根路径时,只有一个引用:'JNI 全局引用'。
这是什么意思?为什么它会保留每个框架实例?
JNI全局引用是指从“本地”代码到由Java垃圾回收器管理的Java对象的引用。其目的是防止在Java代码中没有活动引用的情况下仍被本地代码使用的对象被回收。
JFrame是一个java.awt.Window
,与一个“本地”窗口对象相关联。当您完全完成特定的JFrame实例时,应调用其dispose()
方法进行清理。
我不确定是否有任何本地代码创建了对JFrame的全局引用,但这似乎很可能。如果有,这将阻止JFrame被垃圾回收。如果您正在创建许多窗口(或子类)并发现它们永远不会被回收,请确保它们已被处理。
维基百科对Java Native Interface有一个很好的概述,它实质上允许Java与使用其他语言编写的本地操作系统库进行通信。
JNI全局引用容易出现内存泄漏问题,因为它们不会自动进行垃圾回收,程序员必须显式释放它们。如果您自己没有编写任何JNI代码,则您使用的库可能存在内存泄漏问题。
编辑这里有关于本地引用和全局引用的更多信息,以及为什么使用全局引用(以及如何释放它们)。
在修复JavaFX应用程序中的内存泄漏问题时,我也遇到了这个确切的问题。最终问题是由于我在代码中运行调试模式并设置了几个断点。这似乎导致对象成为“JNI全局引用”,并且在没有明显原因的情况下保留在内存中。当我关闭调试模式时,一切都正常工作!