Skip to Main Content

Java Programming

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

memory leak due to final local variable?

tbee-JavaNetJul 30 2008 — edited Sep 1 2008
I'm not quite clear what I'm seeing here.

Currently I'm trying to solve a memory leak in a rather complex application. Below is a typical path-to-GC trace of one of the most present objects; an instance of EclipseLink's ReadAllQuery... Points 10 through 15 also include, before the dash, the variable name holding the reference (copying a trace from Eclipse's Memory Analyzer Tool does not include that info, so I added it manually where relevant):

1. org.eclipse.persistence.queries.ReadAllQuery
2. org.eclipse.persistence.internal.indirection.QueryBasedValueHolder
3. org.eclipse.persistence.internal.indirection.UnitOfWorkQueryValueHolder
4. org.eclipse.persistence.indirection.IndirectList
5. nl.reinders.bm.Address
5. java.lang.Object[]
7. java.util.Vector
8. org.eclipse.persistence.indirection.IndirectList
9. nl.reinders.bm.Relation
10. *[24]* - java.lang.Object[]
11. elementData - java.util.ArrayList
12. iEntities - org.tbee.swing.jpa.JpaEntitySearchResultTableModel
13. tableModel - org.tbee.swing.table.TableSorter
14. val$lJpaEntitySearchResultTableModel - org.tbee.swing.jpa.JpaEntitySearchBuilder$11
15. *[3]* - java.lang.Object[]
16. javax.swing.event.EventListenerList
17. javax.swing.JButton

A quick walkthrough of the list above:
1. to 9. are references inside my business model, not relevant
10. to 12. an arraylist in the JpaEntitySearchResultTableModel holding a number of references to multiple Relation-entities a.o. this one
13. a TableSorter like we all know and love
14. ahhhh, this we will be getting back to
15.-17. The event listeners registered to a JButton

Let me show the code for point 13. to 17, where I've filtered out for now what I consider static:
	protected List<T> searchDialog(Component component, String title, final int selectMode, final List<T> returnSearchResult)
	{		
		// prep the dialog
		final JDialog lJDialog = new JDialog(component, title, Dialog.ModalityType.DOCUMENT_MODAL );
		lJDialog.setDefaultCloseOperation( JDialog.DISPOSE_ON_CLOSE );

		// return value
		final List<T> lList = new ArrayList<T>();
			
		// result table
		final JpaEntitySearchResultTableModel<T> lJpaEntitySearchResultTableModel = new JpaEntitySearchResultTableModel<T>( getEntityClass() ); // must be done before the setModel
		final TableSorter lTableSorter = new TableSorter(lJpaEntitySearchResultTableModel);
		final JpaEntitySearchResultTable lJpaEntitySearchResultTable = new JpaEntitySearchResultTable();
		lTableSorter.setTable(lJpaEntitySearchResultTable);
		lJpaEntitySearchResultTable.setModel(lTableSorter);
		lJpaEntitySearchResultTable.setSelectionMode( ListSelectionModel.MULTIPLE_INTERVAL_SELECTION ); // we allow always multiselect so the result can be copied
		...
		final JButton lOkButton = new JButton( Internationalization.get().translate(this, "ok"), new ImageIcon(JpaObjectNavigatorBar.class.getResource("icon_ok.png")) );
		lOkButton.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e)
		{
			int[] lSelectedRows = lJpaEntitySearchResultTable.getSelectedRows();
			for (int lIdx = 0; lIdx < lSelectedRows.length; lIdx++)
			{
				T lEntity = lJpaEntitySearchResultTableModel.getEntity( lTableSorter.convertRowIndexToModel( lSelectedRows[lIdx] ) );
				lList.add( lEntity );
			}
				
			// optionally return the whole SearchResult not only what was selected
			if (returnSearchResult != null)
			{
				returnSearchResult.clear();
				for (int lIdx = 0; lIdx < lJpaEntitySearchResultTableModel.getRowCount(); lIdx++)
				{
					T lEntity = lJpaEntitySearchResultTableModel.getEntity( lTableSorter.convertRowIndexToModel( lIdx ) );
					returnSearchResult.add( lEntity );
				}
			}
				
			// hide the dialog (thus allowing the execution to continue below)
			lJDialog.setVisible(false);
		}});		
		...
		lJDialog.setVisible(true); // thread is blocked here until the dialog is closed			

		// now return the selected values
		return lList;
	}		
There are a number of things to notice:
A. a final list parameter: returnSearchResult
B. a final local JDialog
C. a final local variable: lList
D. a final local variable of a special TableModel: lJpaEntitySearchResultTableModel
E. the handling of a button copying data from the: lJpaEntitySearchResultTableModel to the local list (which is returned later on) and also optionally into the final parameter

Now back to the memory trace. I'm experiencing unexpected increases in memory usage. The dialog can be opened 10 times without a problem and then all of a suddent the Nth time the memory increases with like 50MB. At the time the dump was made the dialog was not visible, which means as much as that the method above is not executed. I used jconsole to first do a GC and then write a hprof file.

The trace continues up all the way to the JDialog.

How can it be possible that a reference is being held by a local final variable as indicated by 14 in the path-to-GC? It says that lJpaEntitySearchResultTableModel holds a reference via the TableModel to my business entities. Pausing the VM in eclipse shows there is no thread inside that method!
How can it be the JDialog is still present in the memory trace? The jdialog should have been disposed.
Comments
Locked Post
New comments cannot be posted to this locked post.
Post Details
Locked on Sep 29 2008
Added on Jul 30 2008
60 comments
762 views