void (final List<ThreadGroupReferenceProxyImpl> pathToThread, final ThreadReferenceProxyImpl thread, final boolean expand) { LOG.assertTrue(SwingUtilities.isEventDispatchThread()); class MyTreeModelAdapter extends TreeModelAdapter { private void structureChanged(DebuggerTreeNodeImpl node) { for (Enumeration enumeration = node.children(); enumeration.hasMoreElements(); ) { DebuggerTreeNodeImpl child = (DebuggerTreeNodeImpl)enumeration.nextElement(); nodeChanged(child); } } private void nodeChanged(DebuggerTreeNodeImpl debuggerTreeNode) { if (pathToThread.isEmpty()) { if (debuggerTreeNode.getDescriptor() instanceof ThreadDescriptorImpl && ((ThreadDescriptorImpl)debuggerTreeNode.getDescriptor()).getThreadReference() == thread) { removeListener(); final TreePath treePath = new TreePath(debuggerTreeNode.getPath()); setSelectionPath(treePath); if (expand && !isExpanded(treePath)) { expandPath(treePath); } } } else { if (debuggerTreeNode.getDescriptor() instanceof ThreadGroupDescriptorImpl && ((ThreadGroupDescriptorImpl)debuggerTreeNode.getDescriptor()).getThreadGroupReference() == pathToThread.get(0)) { pathToThread.remove(0); expandPath(new TreePath(debuggerTreeNode.getPath())); } } } private void removeListener() { final TreeModelAdapter listener = this; SwingUtilities.invokeLater(() -> getModel().removeTreeModelListener(listener)); } @Override public void treeStructureChanged(TreeModelEvent event) { if (event.getPath().length <= 1) { removeListener(); return; } structureChanged((DebuggerTreeNodeImpl)event.getTreePath().getLastPathComponent()); } } MyTreeModelAdapter listener = new MyTreeModelAdapter(); listener.structureChanged((DebuggerTreeNodeImpl)getModel().getRoot()); getModel().addTreeModelListener(listener); }