简体   繁体   English

你为什么要处理一个超出范围的java.awt.Window?

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

One of the memory leaks I've discovered in our application is the java.awt.Window.allWindows private static field, which keeps track of every Window instantiated. 我在我们的应用程序中发现的一个内存泄漏是java.awt.Window.allWindows私有静态字段,它跟踪实例化的每个Window We have dialog boxes that are created, used, and then forgotten, and the expectation was that these would go away and be garbage collected. 我们创建,使用,然后忘记了对话框,期望这些对话框会消失并被垃圾收集。 This private field keeps them in scope, indefinitely, until the dispose() method is called on them. 这个私有字段无限期地将它们保留在范围内,直到在它们上调用dispose()方法。 And by definition, we can't do that when they've gone out of scope. 根据定义,当他们超出范围时,我们不能这样做。

I don't understand why this is designed this way. 我不明白为什么这是这样设计的。 It seems contrary to the spirit of garbage collection to have to explicitly let the system know when I'm done with a Window object. 与垃圾收集的精神相反,当我完成Window对象时,必须明确地让系统知道。 Obviously I'm done with it, as it is out of scope. 显然我已经完成了它,因为它超出了范围。

I understand what the dispose() method is doing: getting rid of system peer objects. 我理解dispose()方法正在做什么:摆脱系统对等对象。 I do understand that this is outside of Java and that you need some way to do that and that Swing shouldn't just lose track of those objects, or else it would have a memory leak. 我确实理解这是在Java之外,你需要一些方法来做到这一点,并且Swing不应该只是失去对这些对象的跟踪,否则它会有内存泄漏。 But what is accomplished by keeping a reference to my Window around forever, when I am never going to use it again? 但是,当我永远不再使用它时,通过永久保持对我的Window的引用来实现什么?

Can someone explain why this is necessary? 有人可以解释为什么这是必要的吗?

I hate to say it, but that's just how a GUI works. 我不想这么说,但这就是GUI的工作原理。

Windows are non-blocking. Windows是非阻塞的。 Meaning that once you create one in code, your code continues to execute. 这意味着一旦在代码中创建一个代码,代码就会继续执行。

This means that your Window probably goes out of scope immediately after creation, unless you explicitly stored a reference to it somewhere else. 这意味着您的Window可能会在创建后立即超出范围,除非您在其他位置明确存储了对它的引用。 The Window is still on screen at this point. 此时窗口仍在屏幕上。

This also means you need some other way to get rid of it when you're done with it. 这也意味着当你完成它时,你还需要一些其他方法来摆脱它。 Enter the Window dispose() method, which can be called from within one of the Window's listeners. 输入Window dispose()方法,该方法可以从一个Window的侦听器中调用。

This might explain it: AWT Threading Issues 这可以解释一下: AWT线程问题

Simply, there's a lot more going on in the JVM than just the visible components, with background threads and so on. 简单地说,JVM中除了可见组件,后台线程等之外还有很多其他内容。 These threads and other resources are maintained until the last window on the JVM has been disposed, after which they are tidied up, and the JVM can then exit cleanly. 维护这些线程和其他资源,直到JVM上的最后一个窗口被放置,然后它们被整理,然后JVM可以干净地退出。 So every window, frame and dialog window that you use is essentially holding a lock on the JVM to prevent it from quitting, and you have to manually manage this with calls to dispose() . 因此,您使用的每个窗口,框架和对话框窗口实际上都是锁定JVM以防止它退出,您必须通过调用dispose()手动管理它。

I agree it's a bit of a bugger. 我同意这是一个bugger。 I've run afoul of this a few times myself. 我自己也曾多次与此发生过冲突。

In Java when you have native code (which is what the peers of these windows components are), you need to keep a reference to prevent the garbage collector from trying to garbage collect the object while the native pointers are still around, which would cause all kinds of bad stuff (VM crashes, etc.). 在Java中,当你有本机代码(这些是这些windows组件的同行)时,你需要保留一个引用来防止垃圾收集器在本机指针仍然存在的情况下尝试垃圾收集对象,这将导致所有各种不好的东西(VM崩溃等)。

See, for example, the discussion here . 例如,请参阅此处的讨论。

The dispose() method destroys the object held by the WindowEvent object. dispose()方法销毁WindowEvent对象持有的对象。 It does not kill the application/program. 它不会杀死应用程序/程序。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM