Skip to content

Commit 090e5b8

Browse files
committed
GH-445 renderer for SkipNode added
1 parent da9650e commit 090e5b8

File tree

2 files changed

+92
-20
lines changed

2 files changed

+92
-20
lines changed

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

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,12 @@
2727
import org.graalvm.visualvm.lib.jfluid.heap.Field;
2828
import org.graalvm.visualvm.lib.jfluid.heap.FieldValue;
2929
import org.graalvm.visualvm.lib.jfluid.heap.Instance;
30-
import org.graalvm.visualvm.lib.jfluid.heap.JavaClass;
3130
import org.graalvm.visualvm.lib.jfluid.heap.ObjectFieldValue;
32-
import org.openide.util.NbBundle;
3331

3432
/**
3533
*
3634
* @author Tomas Hurka
3735
*/
38-
@NbBundle.Messages({
39-
"HeapPatterns_SkippedInstances={0} ({1} instances of {2})"
40-
})
4136
final class HeapPatterns {
4237

4338
static PathToGCRootPlugin.SkipNode processGCRootReference(ObjectFieldValue reference) {
@@ -56,14 +51,12 @@ static PathToGCRootPlugin.SkipNode processGCRootReference(ObjectFieldValue refer
5651
ref = oval;
5752
}
5853
if (skipped>1) {
59-
JavaClass jcls = ref.getDefiningInstance().getJavaClass();
60-
String text = Bundle.HeapPatterns_SkippedInstances(ref.getField().getName(), skipped, jcls.getName());
61-
return new PathToGCRootPlugin.SkipNode(text, ref);
54+
return new PathToGCRootPlugin.SkipNode(ref, skipped);
6255
}
6356
return null;
6457
}
6558

66-
static ObjectFieldValue getValueOfField(Instance i, Field f) {
59+
private static ObjectFieldValue getValueOfField(Instance i, Field f) {
6760
for (FieldValue val : i.getFieldValues()) {
6861
if (val instanceof ObjectFieldValue) {
6962
ObjectFieldValue oval = (ObjectFieldValue) val;

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

Lines changed: 90 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import java.awt.GridBagLayout;
3131
import java.awt.Insets;
3232
import java.awt.event.ActionEvent;
33+
import java.text.NumberFormat;
3334
import java.util.ArrayList;
3435
import java.util.Collection;
3536
import java.util.Collections;
@@ -38,6 +39,7 @@
3839
import java.util.List;
3940
import java.util.Map;
4041
import java.util.Objects;
42+
import javax.swing.Icon;
4143
import javax.swing.ImageIcon;
4244
import javax.swing.JButton;
4345
import javax.swing.JCheckBoxMenuItem;
@@ -47,6 +49,8 @@
4749
import javax.swing.SortOrder;
4850
import javax.swing.SwingUtilities;
4951
import org.graalvm.visualvm.heapviewer.HeapContext;
52+
import org.graalvm.visualvm.heapviewer.java.ClassNode;
53+
import org.graalvm.visualvm.heapviewer.java.ClassNodeRenderer;
5054
import org.graalvm.visualvm.heapviewer.java.InstanceNode;
5155
import org.graalvm.visualvm.heapviewer.java.InstanceNodeRenderer;
5256
import org.graalvm.visualvm.heapviewer.java.InstanceReferenceNode;
@@ -62,6 +66,7 @@
6266
import org.graalvm.visualvm.heapviewer.swing.LinkButton;
6367
import org.graalvm.visualvm.heapviewer.ui.HeapViewPlugin;
6468
import org.graalvm.visualvm.heapviewer.ui.HeapViewerActions;
69+
import org.graalvm.visualvm.heapviewer.ui.HeapViewerRenderer;
6570
import org.graalvm.visualvm.heapviewer.ui.TreeTableView;
6671
import org.graalvm.visualvm.heapviewer.ui.TreeTableViewColumn;
6772
import org.graalvm.visualvm.heapviewer.ui.UIThresholds;
@@ -78,6 +83,9 @@
7883
import org.graalvm.visualvm.lib.profiler.api.icons.ProfilerIcons;
7984
import org.graalvm.visualvm.lib.ui.UIUtils;
8085
import org.graalvm.visualvm.lib.ui.swing.renderer.LabelRenderer;
86+
import org.graalvm.visualvm.lib.ui.swing.renderer.MultiRenderer;
87+
import org.graalvm.visualvm.lib.ui.swing.renderer.NormalBoldGrayRenderer;
88+
import org.graalvm.visualvm.lib.ui.swing.renderer.ProfilerRenderer;
8189
import org.openide.util.NbBundle;
8290
import org.openide.util.NbPreferences;
8391
import org.openide.util.lookup.ServiceProvider;
@@ -375,7 +383,7 @@ private static Collection<HeapViewerNode> computeInstanceRoots(Instance instance
375383
ObjectFieldValue ref = (ObjectFieldValue)reference;
376384
SkipNode snode = HeapPatterns.processGCRootReference(ref);
377385
if (snode != null) {
378-
ref = snode.getNextReference();
386+
ref = snode.getValue();
379387
nextInstance = ref.getDefiningInstance();
380388
node = snode;
381389
if (firstNode == null) firstNode = node;
@@ -622,24 +630,95 @@ public void setChildren(HeapViewerNode[] ch) {
622630

623631
}
624632

625-
static class SkipNode extends TextNode implements ToRoot {
633+
static class SkipNode extends FieldToRoot {
626634

627-
private ObjectFieldValue reference;
635+
private int skipped;
628636

629-
SkipNode(String text, ObjectFieldValue ref) {
630-
super(text);
631-
reference = ref;
637+
SkipNode(ObjectFieldValue ref, int sk) {
638+
super(ref);
639+
skipped = sk;
632640
}
641+
}
633642

634-
public void setChildren(HeapViewerNode[] ch) {
635-
super.setChildren(ch);
643+
@NbBundle.Messages({
644+
"# {0} - number of skipped nodes",
645+
"SkipNodeRenderer_Instances=in {0} collapsed instances of "
646+
})
647+
static class SkipNodeRenderer extends MultiRenderer implements HeapViewerRenderer {
648+
649+
private final NormalBoldGrayRenderer nameRenderer;
650+
private final LabelRenderer equalsRenderer;
651+
private final ClassNodeRenderer classRenderer;
652+
private final ProfilerRenderer[] renderers;
653+
private final Heap heap;
654+
655+
SkipNodeRenderer(Heap heap) {
656+
this.heap = heap;
657+
nameRenderer = new NormalBoldGrayRenderer() {
658+
public void setValue(Object value, int row) {
659+
SkipNode node = (SkipNode) value;
660+
String name = node.getFieldName();
661+
if (name.startsWith("static ")) { // NOI18N
662+
setNormalValue("static "); // NOI18N
663+
setBoldValue(name.substring("static ".length())); // NOI18N
664+
} else {
665+
setNormalValue(""); // NOI18N
666+
setBoldValue(name);
667+
}
668+
setIcon(Icons.getIcon(ProfilerIcons.NODE_REVERSE));
669+
}
670+
};
671+
equalsRenderer = new LabelRenderer() {
672+
public void setValue(Object value, int row) {
673+
SkipNode node = (SkipNode) value;
674+
setText(Bundle.SkipNodeRenderer_Instances(NumberFormat.getInstance().format(node.skipped)));
675+
setMargin(3, 2, 3, 0);
676+
}
677+
678+
public String toString() {
679+
return " " + getText() + " "; // NOI18N
680+
}
681+
};
682+
classRenderer = new ClassNodeRenderer(heap);
683+
renderers = new ProfilerRenderer[]{nameRenderer, equalsRenderer, classRenderer};
684+
}
685+
686+
public Icon getIcon() {
687+
return nameRenderer.getIcon();
688+
}
689+
690+
public String getShortName() {
691+
return nameRenderer.toString();
692+
}
693+
694+
protected ProfilerRenderer[] valueRenderers() {
695+
return renderers;
636696
}
637697

638-
private ObjectFieldValue getNextReference() {
639-
return reference;
698+
public void setValue(Object value, int row) {
699+
HeapViewerNode node = (HeapViewerNode) value;
700+
701+
nameRenderer.setValue(node, row);
702+
equalsRenderer.setValue(node, row);
703+
classRenderer.setValue(new ClassNode(((SkipNode) node).getJavaClass()), row);
640704
}
641705
}
642-
706+
707+
@ServiceProvider(service = HeapViewerRenderer.Provider.class)
708+
public static class PathToGCRootRendererProvider extends HeapViewerRenderer.Provider {
709+
710+
@Override
711+
public boolean supportsView(HeapContext context, String viewID) {
712+
return "java_objects_gcroots".equals(viewID); // NOI18N
713+
}
714+
715+
@Override
716+
public void registerRenderers(Map<Class<? extends HeapViewerNode>, HeapViewerRenderer> renderers, HeapContext context) {
717+
renderers.put(SkipNode.class, new SkipNodeRenderer(context.getFragment().getHeap()));
718+
}
719+
720+
}
721+
643722
@ServiceProvider(service=HeapViewPlugin.Provider.class, position = 400)
644723
public static class Provider extends HeapViewPlugin.Provider {
645724

0 commit comments

Comments
 (0)