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 的引用来完成什么?
有人可以解释为什么这是必要的吗?
- 当 removeNotify 被调用时,Window 将从 allWindows 中删除。 Windows 包含本地资源,因此应该以与数据库连接相同的方式处理。
-
我的印象是,当我的数据库连接超出范围时,它们会自动关闭。我可能错了。 :) 不过,如今,除了短程序之外,所有这些都由服务器为我管理。
我不想这么说,但这正是 GUI 的工作原理。
Windows 是非阻塞的。这意味着一旦您在代码中创建了一个,您的代码就会继续执行。
这意味着您的 Window 在创建后可能会立即超出范围,除非您在其他地方明确存储了对它的引用。此时窗口仍在屏幕上。
这也意味着当你完成它时,你需要一些其他的方法来摆脱它。输入 Window dispose() 方法,该方法可以从 Window 的一个侦听器中调用。
- 哦!我知道了!人们总是创建他们不保留引用的窗口,但这些窗口仍然可见并正在运行。我只是没有考虑这一点,因为在这种情况下,我们立即使用窗口然后使其不可见,然后忘记它(超出范围)。现在我明白为什么这是 Windows 的默认设置了。我知道某处有一个合理的用例。 :)
-
哦,对了,我应该指出,当它的变量超出范围时,Window 仍然在屏幕上。我会将其编辑到我的答案中,以防有人错过。
这可以解释它:AWT 线程问题
简单地说,在 JVM 中,除了可见组件、后台线程等等之外,还有很多事情要做。这些线程和其他资源会一直维护到 JVM 上的最后一个窗口被释放,然后将它们清理干净,然后 JVM 就可以干净地退出。因此,您使用的每个窗口、框架和对话窗口本质上都在 JVM 上锁定以防止其退出,您必须通过调用 dispose().
手动管理它
我同意这有点过分。我自己也遇到过几次。
dispose() 方法销毁 WindowEvent 对象持有的对象。它不会杀死应用程序/程序。
在 Java 中,当您拥有本机代码时(这些 Windows 组件的对等体就是这样),您需要保留一个引用,以防止垃圾收集器在本机指针仍然存在时尝试对对象进行垃圾收集,这会导致各种坏事(VM崩溃等)。
例如,请参阅此处的讨论。