Skip to content

Commit d1dfc98

Browse files
committed
GH-481 new "GC Roots" column added to classes view
1 parent d52b9ad commit d1dfc98

File tree

7 files changed

+111
-18
lines changed

7 files changed

+111
-18
lines changed

visualvm/heapviewer/manifest.mf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@ AutoUpdate-Show-In-Client: false
33
AutoUpdate-Essential-Module: true
44
OpenIDE-Module: org.graalvm.visualvm.heapviewer/2
55
OpenIDE-Module-Localizing-Bundle: org/graalvm/visualvm/heapviewer/Bundle.properties
6-
OpenIDE-Module-Specification-Version: 2.7
6+
OpenIDE-Module-Specification-Version: 2.8
77

visualvm/heapviewer/src/org/graalvm/visualvm/heapviewer/java/InstanceNode.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,11 @@ public Instance getInstance() {
8383
return instance;
8484
}
8585

86+
public int getGCRoots() {
87+
Heap heap = instance.getJavaClass().getHeap();
88+
return heap.getGCRoots(instance).size();
89+
}
90+
8691
public JavaClass getJavaClass() {
8792
return instance.getJavaClass();
8893
}
@@ -173,6 +178,7 @@ protected Object getValue(DataType type, Heap heap) {
173178
if (type == DataType.CLASS) return getJavaClass();
174179

175180
if (type == DataType.LOGICAL_VALUE) return getLogicalValue();
181+
if (type == DataType.GCROOTS) return getGCRoots();
176182

177183
if (type == DataType.OBJECT_ID) {
178184
Instance i = getInstance();
@@ -214,6 +220,11 @@ public String getName() {
214220
else return super.getName();
215221
}
216222

223+
public int getGCRoots() {
224+
if (getInstance() == null) return DataType.GCROOTS.getNoValue();
225+
else return super.getGCRoots();
226+
}
227+
217228
public String getLogicalValue() {
218229
if (getInstance() == null) return DataType.LOGICAL_VALUE.getNoValue();
219230
else return super.getLogicalValue();

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

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,15 @@
2626
package org.graalvm.visualvm.heapviewer.java.impl;
2727

2828
import java.awt.Font;
29+
import java.util.HashMap;
30+
import java.util.Map;
31+
import org.graalvm.visualvm.heapviewer.java.InstanceNode;
2932
import org.graalvm.visualvm.heapviewer.java.InstancesContainer;
3033
import org.graalvm.visualvm.heapviewer.model.DataType;
3134
import org.graalvm.visualvm.heapviewer.ui.HeapViewerRenderer;
35+
import org.graalvm.visualvm.lib.jfluid.heap.GCRoot;
36+
import org.graalvm.visualvm.lib.jfluid.heap.Heap;
37+
import org.graalvm.visualvm.lib.jfluid.heap.Instance;
3238
import org.graalvm.visualvm.lib.profiler.api.icons.Icons;
3339
import org.graalvm.visualvm.lib.profiler.api.icons.ProfilerIcons;
3440
import org.graalvm.visualvm.lib.ui.swing.renderer.LabelRenderer;
@@ -45,8 +51,12 @@
4551
})
4652
class GCTypeNode extends InstancesContainer.Objects {
4753

54+
private int gcRoots;
55+
private Map<Instance,Long> gcRootMap;
56+
4857
GCTypeNode(String name) {
4958
super(name, DataType.CLASS.getUnsupportedValue());
59+
gcRootMap = new HashMap<>();
5060
}
5161

5262

@@ -62,6 +72,29 @@ protected String getNodesContainerString(String firstNodeIdx, String lastNodeIdx
6272
return Bundle.ClassesContainer_NodesContainer(firstNodeIdx, lastNodeIdx);
6373
}
6474

75+
void addRoot(GCRoot gcroot, Instance i, Heap heap) {
76+
gcRoots++;
77+
Long count = gcRootMap.get(i);
78+
if (count == null) {
79+
count = 1L;
80+
add(i, heap);
81+
} else {
82+
count++;
83+
}
84+
gcRootMap.put(i, count);
85+
}
86+
87+
@Override
88+
protected InstanceNode createNode(Instance instance) {
89+
return new GCInstanceNode(instance);
90+
}
91+
92+
@Override
93+
protected Object getValue(DataType type, Heap heap) {
94+
if (type == DataType.GCROOTS) return gcRoots;
95+
96+
return super.getValue(type, heap);
97+
}
6598

6699
static class Renderer extends LabelRenderer implements HeapViewerRenderer {
67100

@@ -72,4 +105,17 @@ static class Renderer extends LabelRenderer implements HeapViewerRenderer {
72105

73106
}
74107

108+
private class GCInstanceNode extends InstanceNode {
109+
110+
private GCInstanceNode(Instance instance) {
111+
super(instance);
112+
}
113+
114+
@Override
115+
protected Object getValue(DataType type, Heap heap) {
116+
if (type == DataType.GCROOTS) return gcRootMap.get(getInstance());
117+
118+
return super.getValue(type, heap);
119+
}
120+
}
75121
}

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

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -210,26 +210,22 @@ protected String getNodesContainerString(String firstNodeIdx, String lastNodeIdx
210210
}
211211

212212
if (aggregation == 3) {
213-
List<GCTypeNode> tnodes = new ArrayList<>();
214213
Map<String, GCTypeNode> types = new HashMap<>();
215214
for (Instance instance : gcrootInstances) {
216215
Collection<GCRoot> igcroots = heap.getGCRoots(instance);
217-
Set<String> typeSet = new HashSet<>();
218216
for (GCRoot gcroot : igcroots) {
219217
String tname = gcroot.getKind();
220-
if (typeSet.add(tname)) {
221-
GCTypeNode tnode = types.get(tname);
222-
if (tnode == null) {
223-
tnode = new GCTypeNode(tname);
224-
tnodes.add(tnode);
225-
types.put(tname, tnode);
226-
}
227-
tnode.add(gcroot.getInstance(), heap);
218+
GCTypeNode tnode = types.get(tname);
219+
220+
if (tnode == null) {
221+
tnode = new GCTypeNode(tname);
222+
types.put(tname, tnode);
228223
}
224+
tnode.addRoot(gcroot, instance, heap);
229225
}
230226
}
231-
return tnodes.isEmpty() ? new HeapViewerNode[] { new TextNode(GCRoots_Messages.getNoItemsString(viewFilter)) } :
232-
tnodes.toArray(HeapViewerNode.NO_NODES);
227+
return types.isEmpty() ? new HeapViewerNode[] { new TextNode(GCRoots_Messages.getNoItemsString(viewFilter)) } :
228+
types.values().toArray(HeapViewerNode.NO_NODES);
233229
} else {
234230
List<InstancesContainer.Objects> cnodes = new ArrayList<>();
235231
Map<String, InstancesContainer.Objects> classes = new HashMap<>();

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

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,8 @@
8686
})
8787
public class JavaObjectsView extends HeapViewerFeature {
8888

89-
private static final TreeTableView.ColumnConfiguration CCONF_CLASS = new TreeTableView.ColumnConfiguration(DataType.COUNT, null, DataType.COUNT, SortOrder.DESCENDING, Boolean.FALSE);
89+
private static final TreeTableView.ColumnConfiguration CCONF_CLASS = new TreeTableView.ColumnConfiguration(DataType.COUNT, DataType.GCROOTS, DataType.COUNT, SortOrder.DESCENDING, Boolean.FALSE);
90+
private static final TreeTableView.ColumnConfiguration CCONF_GCROOT = new TreeTableView.ColumnConfiguration(DataType.GCROOTS, null, DataType.GCROOTS, SortOrder.DESCENDING, Boolean.TRUE);
9091
private static final TreeTableView.ColumnConfiguration CCONF_INSTANCE = new TreeTableView.ColumnConfiguration(null, DataType.COUNT, DataType.OWN_SIZE, SortOrder.DESCENDING, null);
9192

9293
private static final TreeTableView.ColumnConfiguration CCONF_PRES1 = new TreeTableView.ColumnConfiguration(DataType.COUNT, null, DataType.COUNT, SortOrder.DESCENDING, Boolean.TRUE);
@@ -444,8 +445,21 @@ protected void fireItemStateChanged(ItemEvent e) {
444445
// invoked also from constructor: super(aggregation.getIcon(), selected)
445446
// in this case aggregation is still null, ignore the event...
446447
if (e.getStateChange() == ItemEvent.SELECTED && aggregation != null) {
447-
TreeTableView.ColumnConfiguration cconf = Aggregation.INSTANCES.equals(aggregation) ?
448-
CCONF_INSTANCE : CCONF_CLASS;
448+
TreeTableView.ColumnConfiguration cconf;
449+
switch (aggregation) {
450+
case INSTANCES:
451+
cconf = CCONF_INSTANCE;
452+
break;
453+
case CLASSES:
454+
case PACKAGES:
455+
cconf = CCONF_CLASS;
456+
break;
457+
case TYPES:
458+
cconf = CCONF_GCROOT;
459+
break;
460+
default:
461+
throw new IllegalArgumentException(aggregation.toString());
462+
}
449463
setAggregation(aggregation, cconf);
450464
}
451465
}

visualvm/heapviewer/src/org/graalvm/visualvm/heapviewer/model/DataType.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ public class DataType<T> {
6161

6262
public static final DataType<String> NAME = new DataType<>(String.class, NO_VALUE_STRING, UNSUPPORTED_VALUE_STRING);
6363
public static final DataType<Integer> COUNT = new DataType<>(Integer.class, NO_VALUE_INTEGER, UNSUPPORTED_VALUE_INTEGER);
64+
public static final DataType<Integer> GCROOTS = new DataType<>(Integer.class, NO_VALUE_INTEGER, UNSUPPORTED_VALUE_INTEGER);
6465
public static final DataType<Long> OWN_SIZE = new DataType<>(Long.class, NO_VALUE_LONG, UNSUPPORTED_VALUE_LONG);
6566

6667
public static final DataType<Long> RETAINED_SIZE = new RetainedSize();

visualvm/heapviewer/src/org/graalvm/visualvm/heapviewer/ui/TreeTableViewColumn.java

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@
4545
"TreeTableViewColumn_ColCount=Count",
4646
"TreeTableViewColumn_ColSize=Size",
4747
"TreeTableViewColumn_ColRetained=Retained",
48-
"TreeTableViewColumn_ColObjectId=Object ID"
48+
"TreeTableViewColumn_ColObjectId=Object ID",
49+
"TreeTableViewColumn_GCRoots=GC Roots"
4950
})
5051
public class TreeTableViewColumn extends TableColumn {
5152

@@ -92,7 +93,8 @@ public static TreeTableViewColumn[] classes(Heap heap, boolean sort) {
9293
new Count(heap),
9394
new OwnSize(heap, true, sort),
9495
new RetainedSize(heap),
95-
new ObjectID()
96+
new ObjectID(),
97+
new GCRoots(heap,false,false)
9698
};
9799
}
98100

@@ -215,6 +217,29 @@ public Count(Heap heap, boolean initiallyVisible, boolean initiallySorting) {
215217

216218
}
217219

220+
public static class GCRoots extends TreeTableViewColumn {
221+
222+
private final HideableBarRenderer renderer;
223+
private final int preferredWidth;
224+
225+
public GCRoots(Heap heap) {
226+
this(heap, true, false);
227+
}
228+
229+
public GCRoots(Heap heap, boolean initiallyVisible, boolean initiallySorting) {
230+
super(Bundle.TreeTableViewColumn_GCRoots(), 190, DataType.GCROOTS, initiallyVisible, initiallySorting);
231+
232+
renderer = new HideableBarRenderer(HeapViewerNumberRenderer.decimalInstance(DataType.GCROOTS));
233+
renderer.setMaxValue(Integer.MAX_VALUE / 1000);
234+
preferredWidth = renderer.getMaxNoBarWidth() - 20;
235+
renderer.setMaxValue(heap.getGCRoots().size());
236+
}
237+
238+
public int getPreferredWidth() { return preferredWidth; }
239+
240+
public ProfilerRenderer getRenderer() { return renderer; }
241+
}
242+
218243
public static class OwnSize extends TreeTableViewColumn {
219244

220245
private final HideableBarRenderer renderer;

0 commit comments

Comments
 (0)