package org.gridkit.jvmtool.heapdump.example; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.gridkit.jvmtool.heapdump.HeapHistogram; import org.gridkit.jvmtool.heapdump.HeapWalker; import org.gridkit.jvmtool.util.TextTree; import org.junit.Test; import org.netbeans.lib.profiler.heap.Heap; import org.netbeans.lib.profiler.heap.HeapFactory; import org.netbeans.lib.profiler.heap.Instance; import org.netbeans.lib.profiler.heap.JavaClass; /** * This example demonstrates extracting JSF component trees * from heap dump. * * @author Alexey Ragozin (alexey.ragozin@gmail.com) */ public class JsfTreeExample { /** * This entry point for this example. */ @Test public void check() throws FileNotFoundException, IOException { String dumppath = ""; // path to dump of JEE server Heap heap = HeapFactory.createFastHeap(new File(dumppath)); dumpComponentTree(heap); } /** * Print JSF component tree extracted from heap dump. */ public void dumpComponentTree(Heap heap) { Set<JavaClass> compClasses = new HashSet<JavaClass>(); Set<Instance> roots = new HashSet<Instance>(); Map<Instance, List<Instance>> links = new HashMap<Instance, List<Instance>>(); // Collect all subclasses of javax.faces.component.UIComponent for(JavaClass jc: heap.getAllClasses()) { if (isComponent(jc)) { compClasses.add(jc); } } System.out.println("UIComponent classes: " + compClasses.size()); int total = 0; // Scan whole heap in search for UIComponent instances for(Instance i: heap.getAllInstances()) { if (!compClasses.contains(i.getJavaClass())) { continue; } ++total; // For each node find root and retain it in roots collection Instance v = HeapWalker.valueOf(i, "compositeParent"); v = v != null ? v : HeapWalker.<Instance>valueOf(i, "parent"); if (v == null) { roots.add(i); } else { // collect parent-to-child relations // as they are hard to extract // from parent component instance if (!links.containsKey(v)) { links.put(v, new ArrayList<Instance>()); } links.get(v).add(i); } } System.out.println("Found " + roots.size() + " component tree roots and " + total + " nodes in total"); // Report tree for each root UIComponent found before for(Instance root: roots) { HeapHistogram hh = new HeapHistogram(); // links variable contains all edges in component graphs identified during heap scan collect(hh, root, links); System.out.println(); System.out.println(root.getInstanceId()); System.out.println(hh.formatTop(10)); System.out.println(); // Dump may contain partial trees // Report only reasonably large object clusters if (hh.getTotalCount() > 500) { printTree(root, links); break; } } } private void printTree(Instance root, Map<Instance, List<Instance>> links) { TextTree tree = tree(root, links); System.out.println(tree.printAsTree()); } // TextTree is a helper class to output ASCII formated tree private TextTree tree(Instance node, Map<Instance, List<Instance>> links) { List<TextTree> c = new ArrayList<TextTree>(); List<Instance> cc = links.get(node); if (cc != null) { for(Instance i: cc) { c.add(tree(i, links)); } } return display(node, c.toArray(new TextTree[0])); } private TextTree display(Instance node, TextTree[] children) { String nodeType = simpleName(node.getJavaClass().getName()); String info = "id:" + HeapWalker.valueOf(node, "id"); String el = HeapWalker.valueOf(node, "txt.literal"); if (el != null) { info += " el:" + el.replace('\n', ' '); } TextTree c = TextTree.t("#", children); return children.length == 0 ? TextTree.t(nodeType, TextTree.t(info)) : TextTree.t(nodeType, TextTree.t(info), c); } private void collect(HeapHistogram h, Instance node, Map<Instance, List<Instance>> links) { h.feed(node); List<Instance> cc = links.get(node); if (cc != null) { for(Instance i: cc) { collect(h, i, links); } } } private String simpleName(String name) { int c = name.lastIndexOf('.'); return c < 0 ? name : name.substring(c + 1); } public boolean isComponent(JavaClass type) { if (type.getName().equals("javax.faces.component.UIComponent")) { return true; } else if (type.getSuperClass() != null) { return isComponent(type.getSuperClass()); } else { return false; } } }