Why should you have to dispose() a java.awt.Window

2019-02-13 00:08发布

问题:

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. 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. 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. 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. 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. But what is accomplished by keeping a reference to my Window around forever, when I am never going to use it again?

Can someone explain why this is necessary?

回答1:

I hate to say it, but that's just how a GUI works.

Windows are non-blocking. 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. 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.



回答2:

This might explain it: AWT Threading Issues

Simply, there's a lot more going on in the JVM than just the visible components, with background threads and so on. 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. 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().

I agree it's a bit of a bugger. I've run afoul of this a few times myself.



回答3:

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.).

See, for example, the discussion here.



回答4:

The dispose() method destroys the object held by the WindowEvent object. It does not kill the application/program.