--- old/agent/src/share/classes/sun/jvm/hotspot/oops/ObjectHeap.java Tue Mar 29 13:56:32 2011 +++ new/agent/src/share/classes/sun/jvm/hotspot/oops/ObjectHeap.java Tue Mar 29 13:56:32 2011 @@ -362,7 +362,16 @@ if (klass.equals(compiledICHolderKlassHandle)) return new CompiledICHolder(handle, this); if (klass.equals(methodDataKlassHandle)) return new MethodData(handle, this); } - if (klass.equals(instanceKlassKlassHandle)) return new InstanceKlass(handle, this); + if (klass.equals(instanceKlassKlassHandle)) { + InstanceKlass ik = new InstanceKlass(handle, this); + if (ik.getName().asString().equals("java/lang/Class")) { + // We would normally do this using the vtable style + // lookup but since it's not used for these currently + // it's simpler to just check for the name. + return new InstanceMirrorKlass(handle, this); + } + return ik; + } if (klass.equals(objArrayKlassKlassHandle)) return new ObjArrayKlass(handle, this); if (klass.equals(typeArrayKlassKlassHandle)) return new TypeArrayKlass(handle, this); --- old/agent/src/share/classes/sun/jvm/hotspot/oops/Instance.java Tue Mar 29 13:56:33 2011 +++ new/agent/src/share/classes/sun/jvm/hotspot/oops/Instance.java Tue Mar 29 13:56:33 2011 @@ -64,7 +64,7 @@ public void iterateFields(OopVisitor visitor, boolean doVMFields) { super.iterateFields(visitor, doVMFields); - ((InstanceKlass) getKlass()).iterateNonStaticFields(visitor); + ((InstanceKlass) getKlass()).iterateNonStaticFields(visitor, this); } public void printValueOn(PrintStream tty) { --- old/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java Tue Mar 29 13:56:33 2011 +++ new/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java Tue Mar 29 13:56:33 2011 @@ -241,6 +241,10 @@ // Byteside of the header private static long headerSize; + public long getObjectSize(Oop object) { + return getSizeHelper() * VM.getVM().getAddressSize(); + } + public static long getHeaderSize() { return headerSize; } // Accessors for declared fields @@ -459,7 +463,22 @@ visitor.doCInt(vtableLen, true); visitor.doCInt(itableLen, true); } + } + /* + * Visit the static fields of this InstanceKlass with the obj of + * the visitor set to the oop holding the fields, which is + * currently the java mirror. + */ + public void iterateStaticFields(OopVisitor visitor) { + visitor.setObj(getJavaMirror()); + visitor.prologue(); + iterateStaticFieldsInternal(visitor); + visitor.epilogue(); + + } + + void iterateStaticFieldsInternal(OopVisitor visitor) { TypeArray fields = getFields(); int length = (int) fields.getLength(); for (int index = 0; index < length; index += NEXT_OFFSET) { @@ -477,9 +496,9 @@ return getSuper(); } - public void iterateNonStaticFields(OopVisitor visitor) { + public void iterateNonStaticFields(OopVisitor visitor, Oop obj) { if (getSuper() != null) { - ((InstanceKlass) getSuper()).iterateNonStaticFields(visitor); + ((InstanceKlass) getSuper()).iterateNonStaticFields(visitor, obj); } TypeArray fields = getFields(); --- /dev/null Tue Mar 29 13:56:34 2011 +++ new/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceMirrorKlass.java Tue Mar 29 13:56:34 2011 @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package sun.jvm.hotspot.oops; + +import java.io.*; +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.memory.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.types.*; +import sun.jvm.hotspot.utilities.*; + +// An InstanceKlass is the VM level representation of a Java class. + +public class InstanceMirrorKlass extends InstanceKlass { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + // Just make sure it's there for now + Type type = db.lookupType("instanceMirrorKlass"); + } + + InstanceMirrorKlass(OopHandle handle, ObjectHeap heap) { + super(handle, heap); + } + + public long getObjectSize(Oop o) { + return java_lang_Class.getOopSize(o) * VM.getVM().getAddressSize(); + } + + public void iterateNonStaticFields(OopVisitor visitor, Oop obj) { + super.iterateNonStaticFields(visitor, obj); + // Fetch the real klass from the mirror object + Klass klass = java_lang_Class.asKlass(obj); + if (klass instanceof InstanceKlass) { + ((InstanceKlass)klass).iterateStaticFields(visitor); + } + } +} --- old/agent/src/share/classes/sun/jvm/hotspot/jdi/ClassObjectReferenceImpl.java Tue Mar 29 13:56:35 2011 +++ new/agent/src/share/classes/sun/jvm/hotspot/jdi/ClassObjectReferenceImpl.java Tue Mar 29 13:56:35 2011 @@ -27,7 +27,7 @@ import com.sun.jdi.*; import sun.jvm.hotspot.oops.Instance; import sun.jvm.hotspot.oops.Klass; -import sun.jvm.hotspot.oops.OopUtilities; +import sun.jvm.hotspot.oops.java_lang_Class; public class ClassObjectReferenceImpl extends ObjectReferenceImpl implements ClassObjectReference { @@ -39,7 +39,7 @@ public ReferenceType reflectedType() { if (reflectedType == null) { - Klass k = OopUtilities.classOopToKlass(ref()); + Klass k = java_lang_Class.asKlass(ref()); reflectedType = vm.referenceType(k); } return reflectedType; --- old/agent/src/share/classes/sun/jvm/hotspot/oops/Oop.java Tue Mar 29 13:56:36 2011 +++ new/agent/src/share/classes/sun/jvm/hotspot/oops/Oop.java Tue Mar 29 13:56:35 2011 @@ -103,12 +103,8 @@ // Returns the byte size of this object public long getObjectSize() { Klass k = getKlass(); - if (k instanceof InstanceKlass) { - return ((InstanceKlass)k).getSizeHelper() - * VM.getVM().getAddressSize(); - } - // If it is not an instance, this method should be replaced. - return getHeaderSize(); + // All other types should be overriding getObjectSize directly + return ((InstanceKlass)k).getObjectSize(this); } // Type test operations --- old/agent/src/share/classes/sun/jvm/hotspot/oops/OopUtilities.java Tue Mar 29 13:56:36 2011 +++ new/agent/src/share/classes/sun/jvm/hotspot/oops/OopUtilities.java Tue Mar 29 13:56:36 2011 @@ -74,9 +74,6 @@ private static int THREAD_STATUS_TERMINATED; */ - // java.lang.Class fields - private static OopField hcKlassField; - // java.util.concurrent.locks.AbstractOwnableSynchronizer fields private static OopField absOwnSyncOwnerThreadField; @@ -268,27 +265,6 @@ return null; } - // initialize fields for java.lang.Class - private static void initClassFields() { - if (hcKlassField == null) { - // hc_klass is a HotSpot magic field and hence we can't - // find it from InstanceKlass for java.lang.Class. - TypeDataBase db = VM.getVM().getTypeDataBase(); - int hcKlassOffset = (int) db.lookupType("java_lang_Class").getCIntegerField("klass_offset").getValue(); - if (VM.getVM().isCompressedOopsEnabled()) { - hcKlassField = new NarrowOopField(new NamedFieldIdentifier("hc_klass"), hcKlassOffset, true); - } else { - hcKlassField = new OopField(new NamedFieldIdentifier("hc_klass"), hcKlassOffset, true); - } - } - } - - /** get klassOop field at offset hc_klass_offset from a java.lang.Class object */ - public static Klass classOopToKlass(Oop aClass) { - initClassFields(); - return (Klass) hcKlassField.getValue(aClass); - } - // initialize fields for j.u.c.l AbstractOwnableSynchornizer class private static void initAbsOwnSyncFields() { if (absOwnSyncOwnerThreadField == null) { --- /dev/null Tue Mar 29 13:56:37 2011 +++ new/agent/src/share/classes/sun/jvm/hotspot/oops/java_lang_Class.java Tue Mar 29 13:56:37 2011 @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package sun.jvm.hotspot.oops; + +import java.util.*; + +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.memory.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.types.Type; +import sun.jvm.hotspot.types.TypeDataBase; +import sun.jvm.hotspot.utilities.*; +import sun.jvm.hotspot.jdi.JVMTIThreadState; + +/** A utility class encapsulating useful oop operations */ + +// initialize fields for java.lang.Class +public class java_lang_Class { + + // java.lang.Class fields + static OopField klassField; + static IntField oopSizeField; + + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) { + // klass and oop_size are HotSpot magic fields and hence we can't + // find them from InstanceKlass for java.lang.Class. + Type jlc = db.lookupType("java_lang_Class"); + int klassOffset = (int) jlc.getCIntegerField("klass_offset").getValue(); + if (VM.getVM().isCompressedOopsEnabled()) { + klassField = new NarrowOopField(new NamedFieldIdentifier("klass"), klassOffset, true); + } else { + klassField = new OopField(new NamedFieldIdentifier("klass"), klassOffset, true); + } + int oopSizeOffset = (int) jlc.getCIntegerField("oop_size_offset").getValue(); + oopSizeField = new IntField(new NamedFieldIdentifier("oop_size"), oopSizeOffset, true); + } + + /** get klassOop field at offset hc_klass_offset from a java.lang.Class object */ + public static Klass asKlass(Oop aClass) { + return (Klass) java_lang_Class.klassField.getValue(aClass); + } + + /** get oop_size field at offset oop_size_offset from a java.lang.Class object */ + public static long getOopSize(Oop aClass) { + return java_lang_Class.oopSizeField.getValue(aClass); + } +} --- old/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java Tue Mar 29 13:56:38 2011 +++ new/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java Tue Mar 29 13:56:38 2011 @@ -839,20 +839,18 @@ } private void readSystemProperties() { - final InstanceKlass systemKls = getSystemDictionary().getSystemKlass(); - systemKls.iterate(new DefaultOopVisitor() { - ObjectReader objReader = new ObjectReader(); - public void doOop(sun.jvm.hotspot.oops.OopField field, boolean isVMField) { - if (field.getID().getName().equals("props")) { - try { - sysProps = (Properties) objReader.readObject(field.getValue(systemKls.getJavaMirror())); - } catch (Exception e) { - if (Assert.ASSERTS_ENABLED) { - e.printStackTrace(); - } - } - } - } - }, false); + final InstanceKlass systemKls = getSystemDictionary().getSystemKlass(); + systemKls.iterateStaticFields(new DefaultOopVisitor() { + ObjectReader objReader = new ObjectReader(); + public void doOop(sun.jvm.hotspot.oops.OopField field, boolean isVMField) { + if (field.getID().getName().equals("props")) { + try { + sysProps = (Properties) objReader.readObject(field.getValue(getObj())); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + }); } } --- old/agent/src/share/classes/sun/jvm/hotspot/tools/FinalizerInfo.java Tue Mar 29 13:56:39 2011 +++ new/agent/src/share/classes/sun/jvm/hotspot/tools/FinalizerInfo.java Tue Mar 29 13:56:38 2011 @@ -64,16 +64,16 @@ */ InstanceKlass ik = SystemDictionaryHelper.findInstanceKlass("java.lang.ref.Finalizer"); - final OopField queueField[] = new OopField[1]; - ik.iterateFields(new DefaultOopVisitor() { + final Oop[] queueref = new Oop[1]; + ik.iterateStaticFields(new DefaultOopVisitor() { public void doOop(OopField field, boolean isVMField) { - String name = field.getID().getName(); - if (name.equals("queue")) { - queueField[0] = field; - } + String name = field.getID().getName(); + if (name.equals("queue")) { + queueref[0] = field.getValue(getObj()); + } } - }, false); - Oop queue = queueField[0].getValue(ik); + }); + Oop queue = queueref[0]; InstanceKlass k = (InstanceKlass) queue.getKlass(); --- old/agent/src/share/classes/sun/jvm/hotspot/utilities/HeapGXLWriter.java Tue Mar 29 13:56:39 2011 +++ new/agent/src/share/classes/sun/jvm/hotspot/utilities/HeapGXLWriter.java Tue Mar 29 13:56:39 2011 @@ -164,7 +164,7 @@ protected void writeClass(Instance instance) throws IOException { writeObjectHeader(instance); - Klass reflectedType = OopUtilities.classOopToKlass(instance); + Klass reflectedType = java_lang_Class.asKlass(instance); boolean isInstanceKlass = (reflectedType instanceof InstanceKlass); // reflectedType is null for primitive types (int.class etc). if (reflectedType != null) { --- old/agent/src/share/classes/sun/jvm/hotspot/utilities/HeapHprofBinWriter.java Tue Mar 29 13:56:40 2011 +++ new/agent/src/share/classes/sun/jvm/hotspot/utilities/HeapHprofBinWriter.java Tue Mar 29 13:56:40 2011 @@ -455,7 +455,7 @@ } protected void writeClass(Instance instance) throws IOException { - Klass reflectedKlass = OopUtilities.classOopToKlass(instance); + Klass reflectedKlass = java_lang_Class.asKlass(instance); // dump instance record only for primitive type Class objects. // all other Class objects are covered by writeClassDumpRecords. if (reflectedKlass == null) { --- old/agent/src/share/classes/sun/jvm/hotspot/utilities/ReversePtrsAnalysis.java Tue Mar 29 13:56:41 2011 +++ new/agent/src/share/classes/sun/jvm/hotspot/utilities/ReversePtrsAnalysis.java Tue Mar 29 13:56:41 2011 @@ -117,10 +117,10 @@ public boolean doObj(Oop obj) { if (obj instanceof InstanceKlass) { final InstanceKlass ik = (InstanceKlass) obj; - ik.iterateFields( + ik.iterateStaticFields( new DefaultOopVisitor() { public void doOop(OopField field, boolean isVMField) { - Oop next = field.getValue(ik); + Oop next = field.getValue(getObj()); LivenessPathElement lp = new LivenessPathElement(null, new NamedFieldIdentifier("Static field \"" + field.getID().getName() + @@ -142,8 +142,7 @@ System.err.println(); } } - }, - false); + }); } return false; } --- old/agent/src/share/classes/sun/jvm/hotspot/utilities/soql/JSJavaFactoryImpl.java Tue Mar 29 13:56:42 2011 +++ new/agent/src/share/classes/sun/jvm/hotspot/utilities/soql/JSJavaFactoryImpl.java Tue Mar 29 13:56:42 2011 @@ -158,7 +158,7 @@ } else if (className.equals(javaLangThread())) { res = new JSJavaThread(instance, this); } else if (className.equals(javaLangClass())) { - Klass reflectedType = OopUtilities.classOopToKlass(instance); + Klass reflectedType = java_lang_Class.asKlass(instance); if (reflectedType != null) { JSJavaKlass jk = newJSJavaKlass(reflectedType); // we don't support mirrors of VM internal Klasses --- old/src/share/vm/oops/instanceMirrorKlass.hpp Tue Mar 29 13:56:43 2011 +++ new/src/share/vm/oops/instanceMirrorKlass.hpp Tue Mar 29 13:56:42 2011 @@ -36,6 +36,8 @@ class instanceMirrorKlass: public instanceKlass { + friend class VMStructs; + private: static int _offset_of_static_fields; --- old/src/share/vm/runtime/vmStructs.cpp Tue Mar 29 13:56:43 2011 +++ new/src/share/vm/runtime/vmStructs.cpp Tue Mar 29 13:56:43 2011 @@ -70,6 +70,7 @@ #include "oops/cpCacheKlass.hpp" #include "oops/cpCacheOop.hpp" #include "oops/instanceKlass.hpp" +#include "oops/instanceMirrorKlass.hpp" #include "oops/instanceKlassKlass.hpp" #include "oops/instanceOop.hpp" #include "oops/klass.hpp" @@ -1101,6 +1102,7 @@ declare_type(instanceKlass, Klass) \ declare_type(instanceKlassKlass, klassKlass) \ declare_type(instanceOopDesc, oopDesc) \ + declare_type(instanceMirrorKlass, instanceKlass) \ declare_type(instanceRefKlass, instanceKlass) \ declare_type(klassKlass, Klass) \ declare_type(klassOopDesc, oopDesc) \