public Frame getLastFramePD(JavaThread thread, Address addr) { Address fp = thread.getLastJavaFP(); if (fp == null) { return null; // no information } return new X86Frame(thread.getLastJavaSP(), fp); }
// Get list of Java threads that have called Object.wait on the specified monitor. public List getWaitingThreads(ObjectMonitor monitor) { List pendingThreads = new ArrayList(); for (JavaThread thread = first(); thread != null; thread = thread.next()) { ObjectMonitor waiting = thread.getCurrentWaitingMonitor(); if (monitor.equals(waiting)) { pendingThreads.add(thread); } } return pendingThreads; }
// refer to Threads::get_pending_threads // Get list of Java threads that are waiting to enter the specified monitor. public List getPendingThreads(ObjectMonitor monitor) { List pendingThreads = new ArrayList(); for (JavaThread thread = first(); thread != null; thread = thread.next()) { if (thread.isCompilerThread() || thread.isCodeCacheSweeperThread()) { continue; } ObjectMonitor pending = thread.getCurrentPendingMonitor(); if (monitor.equals(pending)) { pendingThreads.add(thread); } } return pendingThreads; }
/** * Routine for instantiating appropriately-typed wrapper for a JavaThread. Currently needs to be * public for OopUtilities to access it. */ public JavaThread createJavaThreadWrapper(Address threadAddr) { try { JavaThread thread = (JavaThread) virtualConstructor.instantiateWrapperFor(threadAddr); thread.setThreadPDAccess(access); return thread; } catch (Exception e) { throw new RuntimeException( "Unable to deduce type of thread from address " + threadAddr + " (expected type JavaThread, CompilerThread, ServiceThread, JvmtiAgentThread or CodeCacheSweeperThread)", e); } }
// refer to Threads::owning_thread_from_monitor_owner public JavaThread owningThreadFromMonitor(Address o) { if (o == null) return null; for (JavaThread thread = first(); thread != null; thread = thread.next()) { if (o.equals(thread.threadObjectAddress())) { return thread; } } for (JavaThread thread = first(); thread != null; thread = thread.next()) { if (thread.isLockOwned(o)) return thread; } return null; }
/** 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; }
/** Memory operations */ public void oopsDo(AddressVisitor oopVisitor) { // FIXME: add more of VM functionality for (JavaThread thread = first(); thread != null; thread = thread.next()) { thread.oopsDo(oopVisitor); } }