Skip to content

Commit 0563a1d

Browse files
committed
Compute merged references & GC roots only on demand by default, fallback to automatic computation available.
1 parent 5db2232 commit 0563a1d

File tree

2 files changed

+238
-24
lines changed

2 files changed

+238
-24
lines changed

visualvm/heapviewer/src/org/graalvm/visualvm/heapviewer/java/impl/JavaReferencesPlugin.java

Lines changed: 120 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@
2525

2626
package org.graalvm.visualvm.heapviewer.java.impl;
2727

28+
import java.awt.BorderLayout;
29+
import java.awt.GridBagConstraints;
30+
import java.awt.GridBagLayout;
31+
import java.awt.Insets;
2832
import java.awt.event.ActionEvent;
2933
import java.util.Arrays;
3034
import java.util.HashMap;
@@ -35,8 +39,10 @@
3539
import java.util.Objects;
3640
import java.util.Set;
3741
import javax.swing.ImageIcon;
42+
import javax.swing.JButton;
3843
import javax.swing.JCheckBoxMenuItem;
3944
import javax.swing.JComponent;
45+
import javax.swing.JPanel;
4046
import javax.swing.JPopupMenu;
4147
import javax.swing.SortOrder;
4248
import javax.swing.SwingUtilities;
@@ -57,6 +63,7 @@
5763
import org.graalvm.visualvm.heapviewer.model.Progress;
5864
import org.graalvm.visualvm.heapviewer.model.RootNode;
5965
import org.graalvm.visualvm.heapviewer.model.TextNode;
66+
import org.graalvm.visualvm.heapviewer.swing.LinkButton;
6067
import org.graalvm.visualvm.heapviewer.ui.HeapViewPlugin;
6168
import org.graalvm.visualvm.heapviewer.ui.HeapViewerActions;
6269
import org.graalvm.visualvm.heapviewer.ui.HeapViewerRenderer;
@@ -71,6 +78,7 @@
7178
import org.graalvm.visualvm.heapviewer.utils.ProgressIterator;
7279
import org.graalvm.visualvm.lib.jfluid.heap.JavaClass;
7380
import org.graalvm.visualvm.lib.jfluid.heap.Value;
81+
import org.graalvm.visualvm.lib.ui.UIUtils;
7482
import org.graalvm.visualvm.lib.ui.swing.renderer.LabelRenderer;
7583
import org.openide.util.Lookup;
7684
import org.openide.util.NbBundle;
@@ -85,31 +93,36 @@
8593
"JavaReferencesPlugin_Name=References",
8694
"JavaReferencesPlugin_Description=References",
8795
"JavaReferencesPlugin_NoReferences=<no references>",
88-
"JavaReferencesPlugin_NoReferencesFiltered=<merged references disabled>",
96+
// "JavaReferencesPlugin_NoReferencesFiltered=<merged references disabled>",
8997
"JavaReferencesPlugin_NoSelection=<no class or instance selected>",
9098
"JavaReferencesPlugin_MoreNodes=<another {0} references left>",
9199
"JavaReferencesPlugin_SamplesContainer=<sample {0} references>",
92100
"JavaReferencesPlugin_NodesContainer=<references {0}-{1}>",
93101
"JavaReferencesPlugin_IMoreNodes=<another {0} instances left>",
94102
"JavaReferencesPlugin_ISamplesContainer=<sample {0} instances>",
95103
"JavaReferencesPlugin_INodesContainer=<instances {0}-{1}>",
96-
"JavaReferencesPlugin_MenuShowMergedReferences=Show Merged References",
104+
"JavaReferencesPlugin_ComputeMergedReferencesLbl=Compute Merged References",
105+
"JavaReferencesPlugin_ComputeMergedReferencesTtp=Compute merged references for the selected class",
106+
"JavaReferencesPlugin_AutoComputeMergedReferencesLbl=Compute Merged References Automatically",
107+
"JavaReferencesPlugin_AutoComputeMergedReferencesTtp=Compute merged references automatically for each selected class",
97108
"JavaReferencesPlugin_MenuShowLogicalReferences=Show Logical References"
98109
})
99110
class JavaReferencesPlugin extends HeapViewPlugin {
100111

101112
private static final TreeTableView.ColumnConfiguration CCONF_CLASS = new TreeTableView.ColumnConfiguration(DataType.COUNT, null, DataType.COUNT, SortOrder.DESCENDING, Boolean.FALSE);
102113
private static final TreeTableView.ColumnConfiguration CCONF_INSTANCE = new TreeTableView.ColumnConfiguration(null, DataType.COUNT, DataType.NAME, SortOrder.UNSORTED, null);
103114

104-
private static final String KEY_MERGED_REFERENCES = "mergedReferences"; // NOI18N
115+
private static final String KEY_MERGED_REFERENCES = "autoMergedReferences"; // NOI18N
105116
private static final String KEY_LOGICAL_REFERENCES = "logicalkReferences"; // NOI18N
106117

107-
private volatile boolean mergedReferences = readItem(KEY_MERGED_REFERENCES, true);
118+
private volatile boolean mergedReferences = readItem(KEY_MERGED_REFERENCES, false);
108119
private volatile boolean logicalReferences = readItem(KEY_LOGICAL_REFERENCES, true);
109120

110121
private final Heap heap;
111122
private HeapViewerNode selected;
112123

124+
private volatile boolean mergedRequest;
125+
113126
private final TreeTableView objectsView;
114127

115128

@@ -128,6 +141,8 @@ public JavaReferencesPlugin(HeapContext context, HeapViewerActions actions, fina
128141
};
129142
objectsView = new TreeTableView("java_objects_references", context, actions, columns) { // NOI18N
130143
protected HeapViewerNode[] computeData(RootNode root, Heap heap, String viewID, HeapViewerNodeFilter viewFilter, List<DataType> dataTypes, List<SortOrder> sortOrders, Progress progress) throws InterruptedException {
144+
if (mergedRequest) return HeapViewerNode.NO_NODES;
145+
131146
HeapViewerNode _selected;
132147
synchronized (objectsView) { _selected = selected; }
133148

@@ -137,14 +152,16 @@ protected HeapViewerNode[] computeData(RootNode root, Heap heap, String viewID,
137152
if (wrapper != null) {
138153
SwingUtilities.invokeLater(new Runnable() {
139154
public void run() {
140-
if (!mergedReferences && !CCONF_INSTANCE.equals(objectsView.getCurrentColumnConfiguration()))
141-
objectsView.configureColumns(CCONF_INSTANCE);
142-
else if (mergedReferences && !CCONF_CLASS.equals(objectsView.getCurrentColumnConfiguration()))
155+
// if (!mergedReferences && !CCONF_INSTANCE.equals(objectsView.getCurrentColumnConfiguration()))
156+
// objectsView.configureColumns(CCONF_INSTANCE);
157+
// else if (mergedReferences && !CCONF_CLASS.equals(objectsView.getCurrentColumnConfiguration()))
158+
// objectsView.configureColumns(CCONF_CLASS);
159+
if (!CCONF_CLASS.equals(objectsView.getCurrentColumnConfiguration()))
143160
objectsView.configureColumns(CCONF_CLASS);
144161
}
145162
});
146163

147-
if (!mergedReferences) return new HeapViewerNode[] { new TextNode(Bundle.JavaReferencesPlugin_NoReferencesFiltered()) };
164+
// if (!mergedReferences) return new HeapViewerNode[] { new TextNode(Bundle.JavaReferencesPlugin_NoReferencesFiltered()) };
148165

149166
return computeInstancesReferences(wrapper, root, heap, viewID, null, dataTypes, sortOrders, progress);
150167
} else {
@@ -170,15 +187,18 @@ public void run() {
170187
protected void populatePopup(HeapViewerNode node, JPopupMenu popup) {
171188
if (popup.getComponentCount() > 0) popup.addSeparator();
172189

173-
popup.add(new JCheckBoxMenuItem(Bundle.JavaReferencesPlugin_MenuShowMergedReferences(), mergedReferences) {
190+
popup.add(new JCheckBoxMenuItem(Bundle.JavaReferencesPlugin_AutoComputeMergedReferencesLbl(), mergedReferences) {
174191
@Override
175192
protected void fireActionPerformed(ActionEvent event) {
176193
SwingUtilities.invokeLater(new Runnable() {
177194
@Override
178195
public void run() {
179196
mergedReferences = isSelected();
180197
storeItem(KEY_MERGED_REFERENCES, mergedReferences);
181-
reloadView();
198+
if (CCONF_CLASS.equals(objectsView.getCurrentColumnConfiguration())) { // only update view for class selection
199+
if (!mergedReferences) showMergedView();
200+
reloadView(); // reload even if !mergedReferences to release the currently computed references
201+
}
182202
}
183203
});
184204
}
@@ -192,17 +212,100 @@ protected void fireActionPerformed(ActionEvent event) {
192212
public void run() {
193213
logicalReferences = isSelected();
194214
storeItem(KEY_LOGICAL_REFERENCES, logicalReferences);
195-
reloadView();
215+
if (CCONF_CLASS.equals(objectsView.getCurrentColumnConfiguration())) { // only update view for class selection
216+
reloadView();
217+
}
196218
}
197219
});
198220
}
199221
});
200222
}
201223
};
202224
}
225+
226+
227+
private JComponent component;
228+
229+
private void showObjectsView() {
230+
JComponent c = objectsView.getComponent();
231+
if (c.isVisible()) return;
232+
233+
c.setVisible(true);
234+
235+
component.removeAll();
236+
component.add(c, BorderLayout.CENTER);
237+
238+
mergedRequest = false;
239+
240+
component.invalidate();
241+
component.revalidate();
242+
component.repaint();
243+
}
244+
245+
private void showMergedView() {
246+
JComponent c = objectsView.getComponent();
247+
if (!c.isVisible()) return;
248+
249+
c.setVisible(false);
250+
251+
component.removeAll();
252+
253+
JButton jb = new JButton(Bundle.JavaReferencesPlugin_ComputeMergedReferencesLbl(), Icons.getIcon(ProfilerIcons.NODE_REVERSE)) {
254+
protected void fireActionPerformed(ActionEvent e) {
255+
showObjectsView();
256+
objectsView.reloadView();
257+
}
258+
};
259+
jb.setIconTextGap(jb.getIconTextGap() + 2);
260+
jb.setToolTipText(Bundle.JavaReferencesPlugin_ComputeMergedReferencesTtp());
261+
Insets margin = jb.getMargin();
262+
if (margin != null) jb.setMargin(new Insets(margin.top + 3, margin.left + 3, margin.bottom + 3, margin.right + 3));
263+
264+
265+
LinkButton lb = new LinkButton(Bundle.JavaReferencesPlugin_AutoComputeMergedReferencesLbl()) {
266+
protected void fireActionPerformed(ActionEvent e) {
267+
showObjectsView();
268+
mergedReferences = true;
269+
storeItem(KEY_MERGED_REFERENCES, mergedReferences);
270+
objectsView.reloadView();
271+
}
272+
};
273+
lb.setToolTipText(Bundle.JavaReferencesPlugin_AutoComputeMergedReferencesTtp());
274+
275+
276+
JPanel p = new JPanel(new GridBagLayout());
277+
p.setOpaque(false);
278+
GridBagConstraints g;
279+
280+
g = new GridBagConstraints();
281+
g.fill = GridBagConstraints.HORIZONTAL;
282+
g.gridy = 0;
283+
p.add(jb, g);
284+
285+
g = new GridBagConstraints();
286+
g.fill = GridBagConstraints.HORIZONTAL;
287+
g.gridy = 1;
288+
g.insets = new Insets(10, 0, 0, 0);
289+
p.add(lb, g);
290+
291+
component.add(p);
292+
293+
mergedRequest = true;
294+
295+
component.invalidate();
296+
component.revalidate();
297+
component.repaint();
298+
}
203299

204300
protected JComponent createComponent() {
205-
return objectsView.getComponent();
301+
component = new JPanel(new BorderLayout());
302+
component.setOpaque(true);
303+
component.setBackground(UIUtils.getProfilerResultsBackground());
304+
305+
objectsView.getComponent().setVisible(false); // force init in showObjectsView()
306+
showObjectsView();
307+
308+
return component;
206309
}
207310

208311

@@ -251,6 +354,8 @@ private HeapViewerNode[] computeInstancesReferences(final InstancesWrapper insta
251354
progress.finish();
252355
}
253356

357+
if (values.isEmpty()) return new HeapViewerNode[] { new TextNode(Bundle.JavaReferencesPlugin_NoReferences()) };
358+
254359
NodesComputer<Map.Entry<Long, Integer>> computer = new NodesComputer<Map.Entry<Long, Integer>>(values.size(), UIThresholds.MAX_CLASS_INSTANCES) {
255360
protected boolean sorts(DataType dataType) {
256361
return true;
@@ -289,6 +394,9 @@ protected void nodeSelected(HeapViewerNode node, boolean adjusting) {
289394
selected = node;
290395
}
291396

397+
if (selected != null && !mergedReferences && HeapViewerNode.getValue(selected, DataType.INSTANCES_WRAPPER, heap) != null) showMergedView();
398+
else showObjectsView();
399+
292400
objectsView.reloadView();
293401
}
294402

0 commit comments

Comments
 (0)