/** Runs the analysis algorithm */ public void run() { if (VM.getVM().getRevPtrs() != null) { return; // Assume already done } VM vm = VM.getVM(); rp = new ReversePtrs(); vm.setRevPtrs(rp); Universe universe = vm.getUniverse(); CollectedHeap collHeap = universe.heap(); usedSize = collHeap.used(); visitedSize = 0; // Note that an experiment to iterate the heap linearly rather // than in recursive-descent order has been done. It turns out // that the recursive-descent algorithm is nearly twice as fast // due to the fact that it scans only live objects and (currently) // only a fraction of the perm gen, namely the static fields // contained in instanceKlasses. (Iterating the heap linearly // would also change the semantics of the result so that // ReversePtrs.get() would return a non-null value even for dead // objects.) Nonetheless, the reverse pointer computation is still // quite slow and optimization in field iteration of objects // should be done. if (progressThunk != null) { // Get it started progressThunk.heapIterationFractionUpdate(0); } // Allocate mark bits for heap markBits = new MarkBits(collHeap); // Get a hold of the object heap heap = vm.getObjectHeap(); // Do each thread's roots for (JavaThread thread = VM.getVM().getThreads().first(); thread != null; thread = thread.next()) { ByteArrayOutputStream bos = new ByteArrayOutputStream(); thread.printThreadIDOn(new PrintStream(bos)); String threadDesc = " in thread \"" + thread.getThreadName() + "\" (id " + bos.toString() + ")"; doStack(thread, new RootVisitor("Stack root" + threadDesc)); doJNIHandleBlock(thread.activeHandles(), new RootVisitor("JNI handle root" + threadDesc)); } // Do global JNI handles JNIHandles handles = VM.getVM().getJNIHandles(); doJNIHandleBlock(handles.globalHandles(), new RootVisitor("Global JNI handle root")); doJNIHandleBlock(handles.weakGlobalHandles(), new RootVisitor("Weak global JNI handle root")); // Do Java-level static fields SystemDictionary sysDict = VM.getVM().getSystemDictionary(); sysDict.allClassesDo( new SystemDictionary.ClassVisitor() { public void visit(Klass k) { if (k instanceof InstanceKlass) { final InstanceKlass ik = (InstanceKlass) k; ik.iterateStaticFields( new DefaultOopVisitor() { public void doOop(OopField field, boolean isVMField) { Oop next = field.getValue(getObj()); NamedFieldIdentifier nfi = new NamedFieldIdentifier( "Static field \"" + field.getID().getName() + "\" in class \"" + ik.getName().asString() + "\""); LivenessPathElement lp = new LivenessPathElement(null, nfi); rp.put(lp, next); try { markAndTraverse(next); } catch (AddressException e) { System.err.print( "RevPtrs analysis: WARNING: AddressException at 0x" + Long.toHexString(e.getAddress()) + " while traversing static fields of InstanceKlass "); ik.printValueOn(System.err); System.err.println(); } catch (UnknownOopException e) { System.err.println( "RevPtrs analysis: WARNING: UnknownOopException while " + "traversing static fields of InstanceKlass "); ik.printValueOn(System.err); System.err.println(); } } }); } } }); if (progressThunk != null) { progressThunk.heapIterationComplete(); } // Clear out markBits markBits = null; }