/** Only returns addresses of valid OopHandles */ private Address getOopHandleAddress(int x) { if (Assert.ASSERTS_ENABLED) { Assert.that(x < top(), "out of bounds"); } Address oopAddr = addr.addOffsetTo(handlesField.getOffset() + x * VM.getVM().getOopSize()); OopHandle handle = oopAddr.getOopHandleAt(0); if (VM.getVM().getUniverse().isInReserved(handle) && !VM.getVM().getJNIHandles().isDeletedHandle(handle)) { /* the oop handle is valid only if it is not freed (i.e. reserved in heap) and is not a deleted oop */ return oopAddr; } else { return null; } }
public ByteCodeRewriter(Method method, ConstantPool cpool, byte[] code) { this.method = method; this.cpool = cpool; this.cpCache = cpool.getCache(); this.code = code; this.bytes = VM.getVM().getBytes(); }
public int getFieldOrMethodAt(int which) { if (DEBUG) { System.err.print("ConstantPool.getFieldOrMethodAt(" + which + "): new index = "); } int i = -1; ConstantPoolCache cache = getCache(); if (cache == null) { i = which; } else { // change byte-ordering and go via cache i = cache .getEntryAt(0xFFFF & VM.getVM().getBytes().swapShort((short) which)) .getConstantPoolIndex(); } if (Assert.ASSERTS_ENABLED) { Assert.that(getTagAt(i).isFieldOrMethod(), "Corrupted constant pool"); } if (DEBUG) { System.err.println(i); } int res = getIntAt(i); if (DEBUG) { System.err.println("ConstantPool.getFieldOrMethodAt(" + i + "): result = " + res); } return res; }
public long getLongAt(long index) { int oneHalf = getHandle().getJIntAt(indexOffset(index + 1)); int otherHalf = getHandle().getJIntAt(indexOffset(index)); // buildLongFromIntsPD accepts higher address value, lower address value // in that order. return VM.getVM().buildLongFromIntsPD(oneHalf, otherHalf); }
public void forEachObject(Object[] args) { boolean subtypes = true; Klass kls = null; Callable func = null; switch (args.length) { case 3: { Object b = args[2]; if (b != null && b instanceof Boolean) { subtypes = ((Boolean) b).booleanValue(); } } case 2: { Object k = args[1]; if (k == null) return; if (k instanceof JSJavaKlass) { kls = ((JSJavaKlass) k).getKlass(); } else if (k instanceof String) { kls = SystemDictionaryHelper.findInstanceKlass((String) k); if (kls == null) return; } } case 1: { Object f = args[0]; if (f != null && f instanceof Callable) { func = (Callable) f; } else { // unknown target - just return return; } } break; default: return; } final Callable finalFunc = func; HeapVisitor visitor = new DefaultHeapVisitor() { public boolean doObj(Oop oop) { JSJavaObject jo = factory.newJSJavaObject(oop); if (jo != null) { try { finalFunc.call(new Object[] {jo}); } catch (ScriptException exp) { throw new RuntimeException(exp); } } return false; } }; ObjectHeap heap = VM.getVM().getObjectHeap(); if (kls == null) { kls = SystemDictionaryHelper.findInstanceKlass("java.lang.Object"); } heap.iterateObjectsOfKlass(visitor, kls, subtypes); }
private static void initialize(TypeDataBase db) { if (Assert.ASSERTS_ENABLED) { Assert.that(!VM.getVM().isCore(), "Debug info not used in core build"); } OFFSET_MASK = db.lookupIntConstant("Location::OFFSET_MASK").intValue(); OFFSET_SHIFT = db.lookupIntConstant("Location::OFFSET_SHIFT").intValue(); TYPE_MASK = db.lookupIntConstant("Location::TYPE_MASK").intValue(); TYPE_SHIFT = db.lookupIntConstant("Location::TYPE_SHIFT").intValue(); WHERE_MASK = db.lookupIntConstant("Location::WHERE_MASK").intValue(); WHERE_SHIFT = db.lookupIntConstant("Location::WHERE_SHIFT").intValue(); // Location::Type constants TYPE_NORMAL = db.lookupIntConstant("Location::normal").intValue(); TYPE_OOP = db.lookupIntConstant("Location::oop").intValue(); TYPE_NARROWOOP = db.lookupIntConstant("Location::narrowoop").intValue(); TYPE_INT_IN_LONG = db.lookupIntConstant("Location::int_in_long").intValue(); TYPE_LNG = db.lookupIntConstant("Location::lng").intValue(); TYPE_FLOAT_IN_DBL = db.lookupIntConstant("Location::float_in_dbl").intValue(); TYPE_DBL = db.lookupIntConstant("Location::dbl").intValue(); TYPE_ADDR = db.lookupIntConstant("Location::addr").intValue(); TYPE_INVALID = db.lookupIntConstant("Location::invalid").intValue(); // Location::Where constants WHERE_ON_STACK = db.lookupIntConstant("Location::on_stack").intValue(); WHERE_IN_REGISTER = db.lookupIntConstant("Location::in_register").intValue(); }
// "size helper" == instance size in words public long getSizeHelper() { int lh = getLayoutHelper(); if (Assert.ASSERTS_ENABLED) { Assert.that(lh > 0, "layout helper initialized for instance class"); } return lh / VM.getVM().getAddressSize(); }
private long getElementSize() { if (elementSize != 0) { return elementSize; } else { elementSize = VM.getVM().getOopSize(); } return elementSize; }
static { VM.registerVMInitializedObserver( new Observer() { public void update(Observable o, Object data) { initialize(VM.getVM().getTypeDataBase()); } }); }
/** Convenience routine taking Strings; lookup is done in SymbolTable. */ public Method findMethod(String name, String sig) { SymbolTable syms = VM.getVM().getSymbolTable(); Symbol nameSym = syms.probe(name); Symbol sigSym = syms.probe(sig); if (nameSym == null || sigSym == null) { return null; } return findMethod(nameSym, sigSym); }
public ThreadProxy getThreadProxy(Address addr) { // Addr is the address of the JavaThread. // Fetch the OSThread (for now and for simplicity, not making a // separate "OSThread" class in this package) Address osThreadAddr = osThreadField.getValue(addr); // Get the address of the _thread_id from the OSThread Address threadIdAddr = osThreadAddr.addOffsetTo(osThreadThreadIDField.getOffset()); JVMDebugger debugger = VM.getVM().getDebugger(); return debugger.getThreadForIdentifierAddress(threadIdAddr); }
private void iterateOops( final InstanceKlass ik, final ObjectVisitor visitor, boolean includeSubtypes) { ObjectHeap oh = VM.getVM().getObjectHeap(); oh.iterateObjectsOfKlass( new HeapVisitor() { boolean filterExists; public void prologue(long usedSize) { filterExists = getScriptEngine().get("filter") != null; } public boolean doObj(Oop obj) { dispatchObject(obj, visitor, filterExists); return false; } public void epilogue() {} }, ik, includeSubtypes); }
// Creates new field from index in fields TypeArray private Field newField(int index) { TypeArray fields = getFields(); short signatureIndex = fields.getShortAt(index + SIGNATURE_INDEX_OFFSET); FieldType type = new FieldType((Symbol) getConstants().getObjAt(signatureIndex)); if (type.isOop()) { if (VM.getVM().isCompressedOopsEnabled()) { return new NarrowOopField(this, index); } else { return new OopField(this, index); } } if (type.isByte()) { return new ByteField(this, index); } if (type.isChar()) { return new CharField(this, index); } if (type.isDouble()) { return new DoubleField(this, index); } if (type.isFloat()) { return new FloatField(this, index); } if (type.isInt()) { return new IntField(this, index); } if (type.isLong()) { return new LongField(this, index); } if (type.isShort()) { return new ShortField(this, index); } if (type.isBoolean()) { return new BooleanField(this, index); } throw new RuntimeException("Illegal field type at index " + index); }
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { Type type = db.lookupType("methodOopDesc"); constMethod = new OopField(type.getOopField("_constMethod"), 0); constants = new OopField(type.getOopField("_constants"), 0); methodSize = new CIntField(type.getCIntegerField("_method_size"), 0); maxStack = new CIntField(type.getCIntegerField("_max_stack"), 0); maxLocals = new CIntField(type.getCIntegerField("_max_locals"), 0); sizeOfParameters = new CIntField(type.getCIntegerField("_size_of_parameters"), 0); accessFlags = new CIntField(type.getCIntegerField("_access_flags"), 0); code = type.getAddressField("_code"); vtableIndex = new CIntField(type.getCIntegerField("_vtable_index"), 0); if (!VM.getVM().isCore()) { invocationCounter = new CIntField(type.getCIntegerField("_invocation_counter"), 0); } bytecodeOffset = type.getSize(); /* interpreterEntry = type.getAddressField("_interpreter_entry"); fromCompiledCodeEntryPoint = type.getAddressField("_from_compiled_code_entry_point"); */ objectInitializerName = null; classInitializerName = null; }
private static Symbol javaLangCloneableName() { if (javaLangCloneableName == null) { javaLangCloneableName = VM.getVM().getSymbolTable().probe("java/lang/Cloneable"); } return javaLangCloneableName; }
private long getCapacity() { return VM.getVM().getUniverse().heap().capacity(); }
public int getStackOffset() { if (Assert.ASSERTS_ENABLED) { Assert.that(getWhere() == Where.ON_STACK, "wrong Where"); } return getOffset() * (int) VM.getVM().getIntSize(); }
private long getUsed() { return VM.getVM().getUniverse().heap().used(); }
public Klass getJavaSuper() { SystemDictionary sysDict = VM.getVM().getSystemDictionary(); return sysDict.getObjectKlass(); }
private static Symbol objectInitializerName() { if (objectInitializerName == null) { objectInitializerName = VM.getVM().getSymbolTable().probe("<init>"); } return objectInitializerName; }
public void forEachClass(Object[] args) { boolean withLoader = false; Callable func = null; switch (args.length) { case 2: { Object b = args[1]; if (b instanceof Boolean) { withLoader = ((Boolean) b).booleanValue(); } } case 1: { Object f = args[0]; if (f instanceof Callable) { func = (Callable) f; } else { return; } } break; default: return; } final Callable finalFunc = func; SystemDictionary sysDict = VM.getVM().getSystemDictionary(); if (withLoader) { sysDict.classesDo( new SystemDictionary.ClassAndLoaderVisitor() { public void visit(Klass kls, Oop loader) { JSJavaKlass jk = factory.newJSJavaKlass(kls); if (jk == null) { return; } JSJavaObject k = jk.getJSJavaClass(); JSJavaObject l = factory.newJSJavaObject(loader); if (k != null) { if (k != null) { try { finalFunc.call(new Object[] {k, l}); } catch (ScriptException exp) { throw new RuntimeException(exp); } } } } }); } else { sysDict.classesDo( new SystemDictionary.ClassVisitor() { public void visit(Klass kls) { JSJavaKlass jk = factory.newJSJavaKlass(kls); if (jk == null) { return; } JSJavaClass k = jk.getJSJavaClass(); if (k != null) { if (k != null) { try { finalFunc.call(new Object[] {k}); } catch (ScriptException exp) { throw new RuntimeException(exp); } } } } }); } }
private static Symbol classInitializerName() { if (classInitializerName == null) { classInitializerName = VM.getVM().getSymbolTable().probe("<clinit>"); } return classInitializerName; }
// Accessor public Oop loader() { return VM.getVM().getObjectHeap().newOop(loaderField.getValue(addr)); }
private static synchronized void initialize(TypeDataBase db) { Type type = db.lookupType("Threads"); threadListField = type.getAddressField("_thread_list"); numOfThreadsField = type.getCIntegerField("_number_of_threads"); // Instantiate appropriate platform-specific JavaThreadFactory String os = VM.getVM().getOS(); String cpu = VM.getVM().getCPU(); access = null; // FIXME: find the platform specific PD class by reflection? if (os.equals("solaris")) { if (cpu.equals("sparc")) { access = new SolarisSPARCJavaThreadPDAccess(); } else if (cpu.equals("x86")) { access = new SolarisX86JavaThreadPDAccess(); } else if (cpu.equals("amd64")) { access = new SolarisAMD64JavaThreadPDAccess(); } } else if (os.equals("win32")) { if (cpu.equals("x86")) { access = new Win32X86JavaThreadPDAccess(); } else if (cpu.equals("amd64")) { access = new Win32AMD64JavaThreadPDAccess(); } } else if (os.equals("linux")) { if (cpu.equals("x86")) { access = new LinuxX86JavaThreadPDAccess(); } else if (cpu.equals("amd64")) { access = new LinuxAMD64JavaThreadPDAccess(); } else if (cpu.equals("sparc")) { access = new LinuxSPARCJavaThreadPDAccess(); } else if (cpu.equals("ppc64")) { access = new LinuxPPC64JavaThreadPDAccess(); } else if (cpu.equals("aarch64")) { access = new LinuxAARCH64JavaThreadPDAccess(); } else { try { access = (JavaThreadPDAccess) Class.forName( "sun.jvm.hotspot.runtime.linux_" + cpu.toLowerCase() + ".Linux" + cpu.toUpperCase() + "JavaThreadPDAccess") .newInstance(); } catch (Exception e) { throw new RuntimeException("OS/CPU combination " + os + "/" + cpu + " not yet supported"); } } } else if (os.equals("bsd")) { if (cpu.equals("x86")) { access = new BsdX86JavaThreadPDAccess(); } else if (cpu.equals("amd64") || cpu.equals("x86_64")) { access = new BsdAMD64JavaThreadPDAccess(); } } else if (os.equals("darwin")) { if (cpu.equals("amd64") || cpu.equals("x86_64")) { access = new BsdAMD64JavaThreadPDAccess(); } } if (access == null) { throw new RuntimeException("OS/CPU combination " + os + "/" + cpu + " not yet supported"); } virtualConstructor = new VirtualConstructor(db); // Add mappings for all known thread types virtualConstructor.addMapping("JavaThread", JavaThread.class); if (!VM.getVM().isCore()) { virtualConstructor.addMapping("CompilerThread", CompilerThread.class); virtualConstructor.addMapping("CodeCacheSweeperThread", CodeCacheSweeperThread.class); } virtualConstructor.addMapping("JvmtiAgentThread", JvmtiAgentThread.class); virtualConstructor.addMapping("ServiceThread", ServiceThread.class); }
private static Symbol javaLangObjectName() { if (javaLangObjectName == null) { javaLangObjectName = VM.getVM().getSymbolTable().probe("java/lang/Object"); } return javaLangObjectName; }
/** 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; }
private static Symbol javaIoSerializableName() { if (javaIoSerializableName == null) { javaIoSerializableName = VM.getVM().getSymbolTable().probe("java/io/Serializable"); } return javaIoSerializableName; }
public String toString() { Address handleBase = addr.addOffsetTo(handlesField.getOffset()); Address handleEnd = addr.addOffsetTo(handlesField.getOffset() + top() * VM.getVM().getOopSize()); return "JNIHandleBlock [" + handleBase + ", " + handleEnd + ")"; }
public RevPtrsTreeNodeAdapter(Oop oop, boolean treeTableMode) { super(fid, treeTableMode); children = VM.getVM().getRevPtrs().get(oop); }
public long getInvocationCounter() { if (Assert.ASSERTS_ENABLED) { Assert.that(!VM.getVM().isCore(), "must not be used in core build"); } return invocationCounter.getValue(this); }