Reputation: 53
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
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:
((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. 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