Adan Kuwenyo
Adan Kuwenyo

Reputation: 53

Idle Simple Java Swing Application Memory Leaks

I'm currently investigating a memory leak in one of our applications. After further investigation, I came up with a test of two simple java swing applications that sit idle for almost 14 hours. Both applications consist of 30 JButtons.

The 1st application is using a strong reference for its action listener:

jButton1.addActionListener(new java.awt.event.ActionListener() {
     public void actionPerformed(java.awt.event.ActionEvent evt) {
           jButton1ActionPerformed(evt);
     }
});

The 2nd application is using a weak reference for its action listener:

jButton1.addActionListener(new WeakActionListener(new MyActionListener(), this.jButton1))

Here's the WeakActionListener implementation:

public class WeakActionListener implements ActionListener {

    private WeakReference weakListenerReference;
    private Object source;


    public WeakActionListener(ActionListener listener, Object source) {
        this.weakListenerReference = new WeakReference(listener);
        this.source = source;
    }

    public void actionPerformed(ActionEvent actionEvent) {
        ActionListener actionListener = (ActionListener) this.weakListenerReference.get();
        if(actionListener == null) {
            this.removeListener();
        } else {
            actionListener.actionPerformed(actionEvent);
        }
    }

    private void removeListener() {
        try {
            Method method = source.getClass().getMethod("removeActionListener", new Class[] {ActionListener.class});
            method.invoke(source, new Object[] {this});
        } catch(Exception ex) {
            ex.printStackTrace();
        }
    }

}

I profile both applications using JConsole for 14 hours. I just leave them idle for that time frame. It shows that both applications either using weak reference or strong reference have an increasing memory heap consumption over time.

My question is, is this a bug in Java Swing API? What are the other alternatives in resolving this kind of memory leak?

Thanks in advance!

Upvotes: 3

Views: 1494

Answers (1)

Petr
Petr

Reputation: 6279

JDK actually contains a lot of memory leaks, however the situation you are discribing is not the one of them. The memory consumption grous because even when the app is idle, the OS is not - it sends input events to the app sometimes. Handling these events requires some memory allocations, therefor you see a grouwing heap. And it is probably not collected, because it does not need to - the app has plenty of free memory in the heap, so it does not GC too often.

Additionally, you are using a wrong approach to memory leaks analysis in Java. The right one would be the following:

  1. You create the simplet possible app with the functionality you want to analyse for memory leaks.
  2. You do all steps after which you think the memory should be ready for GC. For GUI-related apps I suggest to add a call to ((SunToolkit)Toolkit.getDefaultToolkit()).realSync() to process all asynchronous calls and events. This is an internal API, so it should not be ised on the real apps, but it is really useful for such experimental apps.
  3. After that you try to allocate some big object to cause an OutOfMemoryError. You can be sure that before throwing OOME Java will collect all free objects. In the catch block for the OOME you simply exit the app with System.exit(0);

Now the most ineteresting part: you should run the app with -Xmx20M to set a low ammount of memory for the heap and -Xrunhprof:format=b,file=<Path to output file>. So when the app finishes, you are sure that all free objects are GC'd because of the OutOfMemory you've caused and hprof will dump a heap of all objects left. You can analize the heap with one of the tools available like jhat or some tools from eclipse.

Upvotes: 2

Related Questions