views:

526

answers:

1

Background

So I read that often memory leaks within Swing applications originate from the use of various listeners (mouse, key, focus, etc). Essentially, you register an object as a listener and forget to deregister the object, the notifier ends up holding onto the reference of the object, leaking a bit of memory.

I knew our application wasn't deregistering listeners and did a bit of research on potential solutions:

I found one approach in dealing with the problem was the use of a WeakReference, full details on the approach with swing listeners can be found here.

I then became curious about how the NetBeans form editor was generating code to clean up after listeners added to the form and discovered that NetBeans was registering listeners via a wrapping object i.e.

argTypeComboBox.addItemListener(new java.awt.event.ItemListener() {
    public void itemStateChanged(java.awt.event.ItemEvent evt) {
      argTypeComboBoxItemStateChanged(evt);
    }
});

But the generated code did not seem to ever clean up by calling removeItemListener.

Questions

Is the wrapping object acting like a weak reference? To me it looks like it could leak a tiny amount of memory (the size of the wrapping object)?

Do you have alternative approaches when dealing with listeners to ensure that they are always garbage collected when you are finished with them?

+3  A: 

First a correction, the potential leak here is not tiny. An anonymous inner class holds a reference to the outer class, so as long as the listener is reachable it will hold on to the whole class.

However, this is typically not a problem, as you are adding listeners to objects on a frame. When that frame is disposed (important that it be disposed, though) and has no more references (which is pretty typical), all of its components become unreachable (if you didn't do anything fancy) and the whole thing gets garbage collected.

I once dealt with an application, however, that did do fancy things, such as registering open windows with a different window, so if the window was closed, it was still registered - big time memory leak - these windows were not tiny.

So the bottom line is that NetBeans isn't doing anything to cause memory "leaks" here as the component is referenced by the frame and not outside of it and the component references the anonymous class, which in turn references the frame - dispose the frame and the whole graph is unreachable, but you do have to be careful with listeners, as they can do this to you.

Yishai
Great clarification Yishai, what was the approach you took to dealing with listeners in the fancy application that had a big time memory leak?
Clinton
@Clinton, once I diagnosed the problem (that took a while, lots of profiling) I was just sure to deregister the listener on window dispose. I don't remember all the details, but that was the key - I didn't know then about weak references as a standard solution to the problem, I might have been able to use that.
Yishai
@Yishai I had been doing deregister as the listener was leaving scope... But it seemed a bit clunky and went looking for a better solution. Thanks again for the correction.
Clinton