关于内存管理:为什么必须 dispose() 超出范围的 java.awt.Window?

Why should you have to dispose() a java.awt.Window that goes out of scope?

我在我们的应用程序中发现的内存泄漏之一是 java.awt.Window.allWindows 私有静态字段,它跟踪每个实例化的 Window。我们有创建、使用然后被遗忘的对话框,并且期望这些对话框会消失并被垃圾收集。这个私有字段将它们无限期地保持在范围内,直到对它们调用 dispose() 方法。根据定义,当它们超出范围时,我们不能这样做。

我不明白为什么要这样设计。当我完成一个 Window 对象时,必须明确地让系统知道这似乎与垃圾收集的精神背道而驰。显然我已经完成了,因为它超出了范围。

我理解 dispose() 方法在做什么:摆脱系统对等对象。我确实明白这在 Java 之外,您需要某种方法来做到这一点,而且 Swing 不应该只是丢失对这些对象的跟踪,否则它会发生内存泄漏。但是,当我永远不会再使用它时,通过永远保留对我的 Window 的引用来完成什么?

有人可以解释为什么这是必要的吗?


我不想这么说,但这正是 GUI 的工作原理。

Windows 是非阻塞的。这意味着一旦您在代码中创建了一个,您的代码就会继续执行。

这意味着您的 Window 在创建后可能会立即超出范围,除非您在其他地方明确存储了对它的引用。此时窗口仍在屏幕上。

这也意味着当你完成它时,你需要一些其他的方法来摆脱它。输入 Window dispose() 方法,该方法可以从 Window 的一个侦听器中调用。


这可以解释它:AWT 线程问题

简单地说,在 JVM 中,除了可见组件、后台线程等等之外,还有很多事情要做。这些线程和其他资源会一直维护到 JVM 上的最后一个窗口被释放,然后将它们清理干净,然后 JVM 就可以干净地退出。因此,您使用的每个窗口、框架和对话窗口本质上都在 JVM 上锁定以防止其退出,您必须通过调用 dispose().

手动管理它

我同意这有点过分。我自己也遇到过几次。


dispose() 方法销毁 WindowEvent 对象持有的对象。它不会杀死应用程序/程序。


在 Java 中,当您拥有本机代码时(这些 Windows 组件的对等体就是这样),您需要保留一个引用,以防止垃圾收集器在本机指针仍然存在时尝试对对象进行垃圾收集,这会导致各种坏事(VM崩溃等)。

例如,请参阅此处的讨论。