views:

795

answers:

3

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  A: 

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.

banjollity
+2  A: 

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.

R. Bemrose
D'oh! I get it! People create windows all the time that they don't keep references to, but the windows are still visible and running. I just wasn't thinking about that because in this situation we're immediately using the window then making it invisible, then forgetting it (going out of scope). Now I see why this is the default for windows. I knew there was a rational use case somewhere. :)
skiphoppy
Oh, right, I should have pointed out that the Window was still on screen when its variable went out of scope. I'll edit that in to my answer just in case someone misses that.
R. Bemrose
A: 

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.

Yishai