I tried with a simple testcase using the NBTestCase#assertGC
method. The benefit of this method is that is prints out the strong references to the object you are checking in case of a memory leak. It also triggers GC by filling the heap with a dumb byte array, forcing the GC to start.
The very simple test case I used
public class ComboBoxMemoryLeak {
public static void main( String[] args ) {
EventQueue.invokeLater( new Runnable() {
@Override
public void run() {
List<WeakReference<JComboBox>> references = new ArrayList<WeakReference<JComboBox>>( );
JComboBox comboBox;
for (int i = 0; i < 1000; i++ ){
comboBox = new JComboBox( );
references.add( new WeakReference<JComboBox>( comboBox ) );
}
comboBox = null;
for ( int i = 0, referencesSize = references.size(); i < referencesSize; i++ ) {
System.out.println( "i = " + i );
WeakReference<JComboBox> weakReference = references.get( i );
NbTestCase.assertGC( "Combobox", weakReference );
}
System.out.println("No memory leak found");
}
} );
}
}
leading to the following trace on my Mac running with JDK1.6
i = 0
Exception in thread "AWT-EventQueue-0" junit.framework.AssertionFailedError: Combobox:
private static sun.awt.AppContext sun.awt.AppContext.mainAppContext->
sun.awt.AppContext@30f7f540-table->
java.util.HashMap@c324b85-table->
[Ljava.util.HashMap$Entry;@770fba26-[8]->
java.util.HashMap$Entry@63adf08f-value->
java.beans.PropertyChangeSupport@4f1b8540-children->
java.util.Hashtable@2305454a-table->
[Ljava.util.Hashtable$Entry;@4a9a4ba3-[0]->
java.util.Hashtable$Entry@6aed0f19-value->
java.beans.PropertyChangeSupport@23597cac-listeners->
sun.awt.EventListenerAggregate@2f39c244-listenerList->
[Ljava.beans.PropertyChangeListener;@2e2e06bd-[0]->
javax.swing.JViewport$1@2a72cf60-this$0->
javax.swing.JViewport@2b9c1dc4-parent->
javax.swing.JScrollPane@b99f7c6-parent->
com.apple.laf.AquaComboBoxPopup@6699166f-comboBox->
javax.swing.JComboBox@3bc634b9
at junit.framework.Assert.fail(Assert.java:50)
at org.netbeans.junit.NbTestCase$4.run(NbTestCase.java:1351)
at org.netbeans.junit.internal.NbModuleLogHandler.whileIgnoringOOME(NbModuleLogHandler.java:143)
at org.netbeans.junit.NbTestCase.assertGC(NbTestCase.java:1309)
at org.netbeans.junit.NbTestCase.assertGC(NbTestCase.java:1285)
at ComboBoxMemoryLeak$1.run(ComboBoxMemoryLeak.java:32)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:677)
at java.awt.EventQueue.access$000(EventQueue.java:85)
at java.awt.EventQueue$1.run(EventQueue.java:638)
at java.awt.EventQueue$1.run(EventQueue.java:636)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:647)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:296)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:211)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:196)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:188)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
So yes, on my machine I would conclude the JComboBox is still present in memory through a reference in the AppContext
. Searching on that leads us to this SO question. I tried connecting JConsole to a main method with a while loop with your statement. Unfortunately my main program threw an OutOfMemoryException
before JConsole could connect, so I couldn't generate a nice picture like trashgod did in his answer.