public final Object getColumnValue(Object row, int columnIndex) { try { Node node = (Node) row; switch (columnIndex) { case 0: if (node.label == null) { IObject obj = snapshot.getObject(node.objectId); node.label = obj.getDisplayName(); node.shallowHeap = obj.getUsedHeapSize(); } return node.label; case 1: if (node.shallowHeap == -1) node.shallowHeap = snapshot.getHeapSize(node.objectId); return node.shallowHeap; case 2: if (node.retainedHeap == -1) node.retainedHeap = snapshot.getRetainedHeapSize(node.objectId); return node.retainedHeap; } } catch (SnapshotException e) { throw new RuntimeException(e); } return null; }
private boolean firstObjectDominatesSecond(int clId, int obj, ISnapshot snapshot) throws SnapshotException { boolean clDominates = false; int dom = snapshot.getImmediateDominatorId(obj); while (dom != -1 && !clDominates) { if (dom == clId) { clDominates = true; } dom = snapshot.getImmediateDominatorId(dom); } return clDominates; }
private void outputGeneralObjectInfo(IObject object, String identation) throws SnapshotException { String clazzName = object.getClazz().getName(); String gcRootInfo = ""; if (snapshot.isGCRoot(object.getObjectId())) { gcRootInfo = GCRootInfo.getTypeSetAsString(snapshot.getGCRootInfo(object.getObjectId())) + " "; } if (snapshot.isClass(object.getObjectId())) { clazzName = "[Class] " + ((IClass) object).getName(); } String objAddr = Long.toString(object.getObjectAddress(), 16); out.println( String.format( "%s<class><![CDATA[%s @ 0x%s]]></class>", identation, gcRootInfo + clazzName, objAddr)); out.println(String.format("%s<id>0x%s</id>", identation.toString(), objAddr)); }
public IResult execute(IProgressListener listener) throws Exception { int[] retainedSet; if (fieldNames == null) retainedSet = snapshot.getRetainedSet(objects.getIds(listener), listener); else retainedSet = snapshot.getRetainedSet(objects.getIds(listener), fieldNames, listener); if (listener.isCanceled()) throw new IProgressListener.OperationCanceledException(); Histogram histogram = snapshot.getHistogram(retainedSet, listener); if (listener.isCanceled()) throw new IProgressListener.OperationCanceledException(); histogram.setLabel( MessageUtil.format(Messages.RetainedSetQuery_RetainedBy, objects.getLabel())); return histogram; }
/** * Get the only object field from the object Used for finding the HashMap from the HashSet * * @param source * @return null if non or duplicates found * @throws SnapshotException */ private IInstance resolveNextField(IObject source) throws SnapshotException { final ISnapshot snapshot = source.getSnapshot(); IInstance ret = null; for (int i : snapshot.getOutboundReferentIds(source.getObjectId())) { if (!snapshot.isArray(i) && !snapshot.isClass(i)) { IObject o = snapshot.getObject(i); if (o instanceof IInstance) { if (ret != null) { ret = null; break; } ret = (IInstance) o; } } } return ret; }
private void write(DataOutputStream out) throws IOException, SnapshotException { Stack<Integer> stack = new Stack<Integer>(); stack.add(-1); while (!stack.isEmpty()) { int objectId = stack.pop(); int[] objectIds = snapshot.getImmediateDominatedIds(objectId); long[] addresses = new long[objectIds.length]; for (int i = 0; i < objectIds.length; i++) addresses[i] = snapshot.mapIdToAddress(objectIds[i]); ArrayUtils.sortDesc(addresses, objectIds); for (int i = 0; i < addresses.length; i++) out.writeLong(addresses[i]); addresses = null; for (int i = objectIds.length - 1; i >= 0; i--) stack.add(objectIds[i]); } }
public ClassloaderLeakDetector(File f) throws Exception { IProgressListener listener = new ConsoleProgressListener(System.out); SnapshotFactory sf = new SnapshotFactory(); snapshot = sf.openSnapshot(f, new HashMap<String, String>(), listener); int[] retainedSet = snapshot.getRetainedSet(snapshot.getGCRoots(), listener); for (int obj : retainedSet) { if (snapshot.isClass(obj)) continue; int clId = snapshot.getClassOf(obj).getClassLoaderId(); if (snapshot.getObject(clId).getClazz().getName().startsWith("sun.")) { continue; } Boolean dominatedAllSoFar = clDominationFlags.get(clId); if (dominatedAllSoFar != null && !dominatedAllSoFar) continue; boolean clDominates = firstObjectDominatesSecond(clId, obj, snapshot); if (!clDominates) { boolean objDominates = firstObjectDominatesSecond(obj, clId, snapshot); if (objDominates) { // System.out.println(String.format( // "Classloader %s IS NOT dominating: %s, but viceversa is true!", snapshot // .getObject(clId).getTechnicalName(), snapshot // .getObject(obj).getTechnicalName())); // printPathToGCRoot(snapshot, obj, false); clDominates = true; } } if (dominatedAllSoFar == null) { clDominationFlags.put(clId, clDominates); } else { // If classloader is not dominating the object and // it has been dominating everything it loaded so far // Then this classloader is no longer dominating. if (!clDominates && dominatedAllSoFar) { clDominationFlags.put(clId, Boolean.FALSE); } } } }
private void printPathToGCRoot(ISnapshot snapshot, int obj, boolean printAllPaths) throws SnapshotException { int dom = snapshot.getImmediateDominatorId(obj); ArrayInt path = new ArrayInt(); path.add(obj); while (dom != -1) { path.add(dom); dom = snapshot.getImmediateDominatorId(dom); } out.println("<dominator-path>"); printObjectFromPath(path.toArray()); out.println("</dominator-path>"); IPathsFromGCRootsComputer pathsFromGCRoots = snapshot.getPathsFromGCRoots(obj, null); List<int[]> paths = new ArrayList<int[]>(); int[] nextShortestPath = pathsFromGCRoots.getNextShortestPath(); int pathCount = 0; int objectCount = 0; while (nextShortestPath != null) { pathCount++; objectCount += nextShortestPath.length; if (pathCount > 500) break; // out.println("<path>"); // printObjectFromPath(nextShortestPath); // out.println("</path>"); if (!printAllPaths) break; paths.add(nextShortestPath); nextShortestPath = pathsFromGCRoots.getNextShortestPath(); } // System.out.println(pathCount + " Paths found for Leak"); // System.out.println(objectCount + " objects in paths"); PathsFromGCRootsTree tree = pathsFromGCRoots.getTree(paths); out.println("<tree>"); System.out.println(outputTree(tree, null, " ") + " objects in path tree"); out.println("</tree>"); }
public synchronized void dispose(ISnapshot snapshot) { for (Iterator<SnapshotEntry> iter = snapshotCache.values().iterator(); iter.hasNext(); ) { SnapshotEntry entry = iter.next(); ISnapshot s = entry.snapshot.get(); if (s == null) { iter.remove(); } else if (s == snapshot) { entry.usageCount--; if (entry.usageCount == 0) { snapshot.dispose(); iter.remove(); } return; } } // just in case the snapshot is not stored anymore if (snapshot != null) snapshot.dispose(); }
public final String suffix(Object row) { Node node = (Node) row; if (node.gcRoots == null) { try { GCRootInfo[] gc = snapshot.getGCRootInfo(node.objectId); node.gcRoots = gc != null ? GCRootInfo.getTypeSetAsString(gc) : Node.NOT_A_GC_ROOT; } catch (SnapshotException e) { throw new RuntimeException(e); } } return node.gcRoots == Node.NOT_A_GC_ROOT ? null : node.gcRoots; }
private void printObjectFromPath(int[] path) throws SnapshotException { StringBuilder closingTags = new StringBuilder(); for (int index = path.length - 1; index >= 0; index--) { IObject object = snapshot.getObject(path[index]); String identation = multiplyStr(" ", path.length - index); out.println(String.format("%s<object id=\"%d\">", identation, xmlObjectCounter++)); outputGeneralObjectInfo(object, identation); closingTags.insert(0, String.format("%s</object>%n", identation)); if (index > 0) { out.println(identation + "<field>"); IObject referencingObject = snapshot.getObject(path[index - 1]); out.println( String.format( "%s <name><![CDATA[%s]]></name>", identation, getReferencingFieldName(object, referencingObject))); closingTags.insert(0, String.format("%s</field>%n", identation)); } } out.print(closingTags); }
public void outputResultsAsXml(PrintStream where) throws SnapshotException { out = where; out.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); out.println("<?xml-stylesheet type=\"text/xsl\" href=\"leaks.xsl\"?>"); out.println("<leaks>"); for (int loader : clDominationFlags.getAllKeys()) { if (clDominationFlags.get(loader)) { IObject loaderObj = snapshot.getObject(loader); out.println( String.format( "<leak>%n<classloader>%s</classloader>%n<id>0x%s</id>", loaderObj.getClazz().getName(), Long.toString(loaderObj.getObjectAddress(), 16))); printPathToGCRoot(snapshot, loader, true); out.println("</leak>"); } } out.println("</leaks>"); }
public IResult execute(IProgressListener listener) throws Exception { FileOutputStream out = null; DataOutputStream dout = null; try { File domTreeBinary = new File(snapshot.getSnapshotInfo().getPrefix() + "Dom_tree.bin"); out = new FileOutputStream(domTreeBinary); dout = new DataOutputStream(out); write(dout); dout.flush(); dout.close(); return new DisplayFileResult(domTreeBinary); } finally { if (out != null) out.close(); if (dout != null) dout.close(); } }
public IResult execute(IProgressListener listener) throws Exception { int[] finalizerThreadObjects = FinalizerThreadQuery.getFinalizerThreads(snapshot); SetInt result = new SetInt(); for (int finalizerThreadObject : finalizerThreadObjects) { Field localsField = ((IInstance) snapshot.getObject(finalizerThreadObject)) .getField("threadLocals"); // $NON-NLS-1$ if (localsField != null) { ObjectReference ref = (ObjectReference) localsField.getValue(); if (ref != null) { // TODO Don't add the thread locals object, but the pairs of // referent and value stored in the thread locals result.add(ref.getObjectId()); } } } return new ObjectListResult.Outbound(snapshot, result.toArray()); }
private int outputTree(PathsFromGCRootsTree tree, IObject objReferencedByRoot, String identation) throws SnapshotException { out.println(String.format("%s<object id=\"%d\">", identation, xmlObjectCounter++)); IObject object = snapshot.getObject(tree.getOwnId()); outputGeneralObjectInfo(object, identation); if (objReferencedByRoot != null) { out.println( String.format( "%s <outbound-ref><![CDATA[%s]]></outbound-ref>", identation, getReferencingFieldName(object, objReferencedByRoot))); } int result = tree.getObjectIds().length; out.println(identation + "<incoming-fields>"); for (int subtree : tree.getObjectIds()) { out.println(identation + " <incoming-field>"); result += outputTree(tree.getBranch(subtree), object, " " + identation); out.println(identation + " </incoming-field>"); } out.println(identation + "</incoming-fields>"); out.println(identation + "</object>"); return result; }
/** * Get a detailed view of the object * * @return the object detail * @throws SnapshotException */ public IObject getObject() throws SnapshotException { return snapshot.getObject(getObjectId()); }
/** * The id of the object * * @return the object id * @throws SnapshotException */ public int getObjectId() throws SnapshotException { return snapshot.mapAddressToId(address); }
@Override public int[] extractEntryIds(IObject list) throws SnapshotException { IProgressListener listener = new VoidProgressListener(); // If there isn't a size, then use an upper limit in case there is a loop int size = super.hasSize() ? getSize(list) : 10000000; String taskMsg = MessageUtil.format( Messages.ExtractListValuesQuery_CollectingElements, size, list.getTechnicalName()); listener.beginTask(taskMsg, size); ArrayInt result = new ArrayInt(); int loopingLimit = size; IObject header = (IObject) list.resolveValue("header"); // LinkedList$Header //$NON-NLS-1$ if (header == null) header = (IObject) list.resolveValue("voidLink"); // LinkedList$Link IBM VM //$NON-NLS-1$ if (header == null) header = (IObject) list.resolveValue("first"); // LinkedList$Node Java 7 //$NON-NLS-1$ if (header == null) {} if (header == null) { // Look for the only object field header = resolveNextFields(list); } if (header == null) return null; IObject previous = header; IObject current = header; if (current.getClazz().getName().equals("java.util.LinkedList$Entry") || //$NON-NLS-1$ current.getClazz().getName().equals("java.util.LinkedList$Link") || //$NON-NLS-1$ current .getClazz() .getName() .equals("java.util.concurrent.LinkedBlockingQueue$Node")) // $NON-NLS-1$ { // Skip over header link for pre Java 7 implementations current = (IObject) header.resolveValue("next"); // $NON-NLS-1$; if (current == null) { // Try without using field names final ISnapshot snapshot = header.getSnapshot(); for (int i : snapshot.getOutboundReferentIds(header.getObjectId())) { IObject o = snapshot.getObject(i); // Exclude the class if (i != header.getClazz().getObjectId()) { if (o.getClazz().equals(header.getClazz())) { // same type as header, so possible next field // don't care whether we get current or previous - // just circle the wrong way current = o; break; } } } } } else { header = null; } while (current != null && current != header && loopingLimit-- > 0) { // Find the element IObject ref = (IObject) current.resolveValue("element"); // $NON-NLS-1$ if (ref == null) ref = (IObject) current.resolveValue("data"); // IBM VM //$NON-NLS-1$ if (ref == null) ref = (IObject) current.resolveValue("item"); // Java 7 //$NON-NLS-1$ if (current.equals(ref)) { // java.util.concurrent.LinkedTransferQueue has a spurious link ref = null; } // Find the next link IObject next = (IObject) current.resolveValue("next"); // $NON-NLS-1$ if (next == null) { // Try without using field names final ISnapshot snapshot = current.getSnapshot(); for (int i : snapshot.getOutboundReferentIds(current.getObjectId())) { IObject o = snapshot.getObject(i); // Exclude the previous field and the class if (i != previous.getObjectId() && i != current.getClazz().getObjectId()) { if (o.getClazz().equals(current.getClazz())) { // same type as current, so possible next field if (next != null) { // Uncertain, so give up next = null; break; } next = o; } else { // possible element if (ref == null) ref = o; } } } } if (ref != null) result.add(ref.getObjectId()); previous = current; current = next; listener.worked(1); // If the user cancels then just return what we have got so far if (listener.isCanceled()) break; } listener.done(); return result.toArray(); }