Path: blob/master/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java
41161 views
/*1* Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324package sun.jvm.hotspot.oops;2526import java.io.*;27import java.util.*;28import sun.jvm.hotspot.classfile.ClassLoaderData;29import sun.jvm.hotspot.debugger.*;30import sun.jvm.hotspot.memory.*;31import sun.jvm.hotspot.memory.Dictionary;32import sun.jvm.hotspot.runtime.*;33import sun.jvm.hotspot.types.*;34import sun.jvm.hotspot.utilities.*;35import sun.jvm.hotspot.utilities.Observable;36import sun.jvm.hotspot.utilities.Observer;3738// An InstanceKlass is the VM level representation of a Java class.3940public class InstanceKlass extends Klass {41static {42VM.registerVMInitializedObserver(new Observer() {43public void update(Observable o, Object data) {44initialize(VM.getVM().getTypeDataBase());45}46});47}4849// field offset constants50private static int ACCESS_FLAGS_OFFSET;51private static int NAME_INDEX_OFFSET;52private static int SIGNATURE_INDEX_OFFSET;53private static int INITVAL_INDEX_OFFSET;54private static int LOW_OFFSET;55private static int HIGH_OFFSET;56private static int FIELD_SLOTS;57private static short FIELDINFO_TAG_SIZE;58private static short FIELDINFO_TAG_OFFSET;5960// ClassState constants61private static int CLASS_STATE_ALLOCATED;62private static int CLASS_STATE_LOADED;63private static int CLASS_STATE_LINKED;64private static int CLASS_STATE_BEING_INITIALIZED;65private static int CLASS_STATE_FULLY_INITIALIZED;66private static int CLASS_STATE_INITIALIZATION_ERROR;6768// _misc_flags constants69private static int MISC_REWRITTEN;70private static int MISC_HAS_NONSTATIC_FIELDS;71private static int MISC_SHOULD_VERIFY_CLASS;72private static int MISC_IS_CONTENDED;73private static int MISC_HAS_NONSTATIC_CONCRETE_METHODS;74private static int MISC_DECLARES_NONSTATIC_CONCRETE_METHODS;75private static int MISC_HAS_BEEN_REDEFINED;76private static int MISC_IS_SCRATCH_CLASS;77private static int MISC_IS_SHARED_BOOT_CLASS;78private static int MISC_IS_SHARED_PLATFORM_CLASS;79private static int MISC_IS_SHARED_APP_CLASS;8081private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {82Type type = db.lookupType("InstanceKlass");83arrayKlasses = new MetadataField(type.getAddressField("_array_klasses"), 0);84methods = type.getAddressField("_methods");85defaultMethods = type.getAddressField("_default_methods");86methodOrdering = type.getAddressField("_method_ordering");87localInterfaces = type.getAddressField("_local_interfaces");88transitiveInterfaces = type.getAddressField("_transitive_interfaces");89fields = type.getAddressField("_fields");90javaFieldsCount = new CIntField(type.getCIntegerField("_java_fields_count"), 0);91constants = new MetadataField(type.getAddressField("_constants"), 0);92sourceDebugExtension = type.getAddressField("_source_debug_extension");93innerClasses = type.getAddressField("_inner_classes");94nonstaticFieldSize = new CIntField(type.getCIntegerField("_nonstatic_field_size"), 0);95staticFieldSize = new CIntField(type.getCIntegerField("_static_field_size"), 0);96staticOopFieldCount = new CIntField(type.getCIntegerField("_static_oop_field_count"), 0);97nonstaticOopMapSize = new CIntField(type.getCIntegerField("_nonstatic_oop_map_size"), 0);98isMarkedDependent = new CIntField(type.getCIntegerField("_is_marked_dependent"), 0);99initState = new CIntField(type.getCIntegerField("_init_state"), 0);100itableLen = new CIntField(type.getCIntegerField("_itable_len"), 0);101if (VM.getVM().isJvmtiSupported()) {102breakpoints = type.getAddressField("_breakpoints");103}104miscFlags = new CIntField(type.getCIntegerField("_misc_flags"), 0);105headerSize = type.getSize();106107// read field offset constants108ACCESS_FLAGS_OFFSET = db.lookupIntConstant("FieldInfo::access_flags_offset").intValue();109NAME_INDEX_OFFSET = db.lookupIntConstant("FieldInfo::name_index_offset").intValue();110SIGNATURE_INDEX_OFFSET = db.lookupIntConstant("FieldInfo::signature_index_offset").intValue();111INITVAL_INDEX_OFFSET = db.lookupIntConstant("FieldInfo::initval_index_offset").intValue();112LOW_OFFSET = db.lookupIntConstant("FieldInfo::low_packed_offset").intValue();113HIGH_OFFSET = db.lookupIntConstant("FieldInfo::high_packed_offset").intValue();114FIELD_SLOTS = db.lookupIntConstant("FieldInfo::field_slots").intValue();115FIELDINFO_TAG_SIZE = db.lookupIntConstant("FIELDINFO_TAG_SIZE").shortValue();116FIELDINFO_TAG_OFFSET = db.lookupIntConstant("FIELDINFO_TAG_OFFSET").shortValue();117118// read ClassState constants119CLASS_STATE_ALLOCATED = db.lookupIntConstant("InstanceKlass::allocated").intValue();120CLASS_STATE_LOADED = db.lookupIntConstant("InstanceKlass::loaded").intValue();121CLASS_STATE_LINKED = db.lookupIntConstant("InstanceKlass::linked").intValue();122CLASS_STATE_BEING_INITIALIZED = db.lookupIntConstant("InstanceKlass::being_initialized").intValue();123CLASS_STATE_FULLY_INITIALIZED = db.lookupIntConstant("InstanceKlass::fully_initialized").intValue();124CLASS_STATE_INITIALIZATION_ERROR = db.lookupIntConstant("InstanceKlass::initialization_error").intValue();125126MISC_REWRITTEN = db.lookupIntConstant("InstanceKlass::_misc_rewritten").intValue();127MISC_HAS_NONSTATIC_FIELDS = db.lookupIntConstant("InstanceKlass::_misc_has_nonstatic_fields").intValue();128MISC_SHOULD_VERIFY_CLASS = db.lookupIntConstant("InstanceKlass::_misc_should_verify_class").intValue();129MISC_IS_CONTENDED = db.lookupIntConstant("InstanceKlass::_misc_is_contended").intValue();130MISC_HAS_NONSTATIC_CONCRETE_METHODS = db.lookupIntConstant("InstanceKlass::_misc_has_nonstatic_concrete_methods").intValue();131MISC_DECLARES_NONSTATIC_CONCRETE_METHODS = db.lookupIntConstant("InstanceKlass::_misc_declares_nonstatic_concrete_methods").intValue();132MISC_HAS_BEEN_REDEFINED = db.lookupIntConstant("InstanceKlass::_misc_has_been_redefined").intValue();133MISC_IS_SCRATCH_CLASS = db.lookupIntConstant("InstanceKlass::_misc_is_scratch_class").intValue();134MISC_IS_SHARED_BOOT_CLASS = db.lookupIntConstant("InstanceKlass::_misc_is_shared_boot_class").intValue();135MISC_IS_SHARED_PLATFORM_CLASS = db.lookupIntConstant("InstanceKlass::_misc_is_shared_platform_class").intValue();136MISC_IS_SHARED_APP_CLASS = db.lookupIntConstant("InstanceKlass::_misc_is_shared_app_class").intValue();137}138139public InstanceKlass(Address addr) {140super(addr);141142// If the class hasn't yet reached the "loaded" init state, then don't go any further143// or we'll run into problems trying to look at fields that are not yet setup.144// Attempted lookups of this InstanceKlass via ClassLoaderDataGraph, ClassLoaderData,145// and Dictionary will all refuse to return it. The main purpose of allowing this146// InstanceKlass to initialize is so ClassLoaderData.getKlasses() will succeed, allowing147// ClassLoaderData.classesDo() to iterate over all Klasses (skipping those that are148// not yet fully loaded).149if (!isLoaded()) {150return;151}152153if (getJavaFieldsCount() != getAllFieldsCount()) {154// Exercise the injected field logic155for (int i = getJavaFieldsCount(); i < getAllFieldsCount(); i++) {156getFieldName(i);157getFieldSignature(i);158}159}160}161162private static MetadataField arrayKlasses;163private static AddressField methods;164private static AddressField defaultMethods;165private static AddressField methodOrdering;166private static AddressField localInterfaces;167private static AddressField transitiveInterfaces;168private static AddressField fields;169private static CIntField javaFieldsCount;170private static MetadataField constants;171private static AddressField sourceDebugExtension;172private static AddressField innerClasses;173private static CIntField nonstaticFieldSize;174private static CIntField staticFieldSize;175private static CIntField staticOopFieldCount;176private static CIntField nonstaticOopMapSize;177private static CIntField isMarkedDependent;178private static CIntField initState;179private static CIntField itableLen;180private static AddressField breakpoints;181private static CIntField miscFlags;182183// type safe enum for ClassState from instanceKlass.hpp184public static class ClassState {185public static final ClassState ALLOCATED = new ClassState("allocated");186public static final ClassState LOADED = new ClassState("loaded");187public static final ClassState LINKED = new ClassState("linked");188public static final ClassState BEING_INITIALIZED = new ClassState("beingInitialized");189public static final ClassState FULLY_INITIALIZED = new ClassState("fullyInitialized");190public static final ClassState INITIALIZATION_ERROR = new ClassState("initializationError");191192private ClassState(String value) {193this.value = value;194}195196public String toString() {197return value;198}199200private String value;201}202203public int getInitStateAsInt() { return (int) initState.getValue(this); }204public ClassState getInitState() {205int state = getInitStateAsInt();206if (state == CLASS_STATE_ALLOCATED) {207return ClassState.ALLOCATED;208} else if (state == CLASS_STATE_LOADED) {209return ClassState.LOADED;210} else if (state == CLASS_STATE_LINKED) {211return ClassState.LINKED;212} else if (state == CLASS_STATE_BEING_INITIALIZED) {213return ClassState.BEING_INITIALIZED;214} else if (state == CLASS_STATE_FULLY_INITIALIZED) {215return ClassState.FULLY_INITIALIZED;216} else if (state == CLASS_STATE_INITIALIZATION_ERROR) {217return ClassState.INITIALIZATION_ERROR;218} else {219throw new RuntimeException("should not reach here");220}221}222223// initialization state quaries224public boolean isLoaded() {225return getInitStateAsInt() >= CLASS_STATE_LOADED;226}227228public boolean isLinked() {229return getInitStateAsInt() >= CLASS_STATE_LINKED;230}231232public boolean isInitialized() {233return getInitStateAsInt() == CLASS_STATE_FULLY_INITIALIZED;234}235236public boolean isNotInitialized() {237return getInitStateAsInt() < CLASS_STATE_BEING_INITIALIZED;238}239240public boolean isBeingInitialized() {241return getInitStateAsInt() == CLASS_STATE_BEING_INITIALIZED;242}243244public boolean isInErrorState() {245return getInitStateAsInt() == CLASS_STATE_INITIALIZATION_ERROR;246}247248public int getClassStatus() {249int result = 0;250if (isLinked()) {251result |= JVMDIClassStatus.VERIFIED | JVMDIClassStatus.PREPARED;252}253254if (isInitialized()) {255if (Assert.ASSERTS_ENABLED) {256Assert.that(isLinked(), "Class status is not consistent");257}258result |= JVMDIClassStatus.INITIALIZED;259}260261if (isInErrorState()) {262result |= JVMDIClassStatus.ERROR;263}264return result;265}266267// Byteside of the header268private static long headerSize;269270public long getObjectSize(Oop object) {271return getSizeHelper() * VM.getVM().getAddressSize();272}273274public long getSize() { // in number of bytes275long wordLength = VM.getVM().getBytesPerWord();276long size = getHeaderSize() +277(getVtableLen() +278getItableLen() +279getNonstaticOopMapSize()) * wordLength;280if (isInterface()) {281size += wordLength;282}283return alignSize(size);284}285286private int getMiscFlags() {287return (int) miscFlags.getValue(this);288}289290public static long getHeaderSize() { return headerSize; }291292public short getFieldAccessFlags(int index) {293return getFields().at(index * FIELD_SLOTS + ACCESS_FLAGS_OFFSET);294}295296public short getFieldNameIndex(int index) {297if (index >= getJavaFieldsCount()) throw new IndexOutOfBoundsException("not a Java field;");298return getFields().at(index * FIELD_SLOTS + NAME_INDEX_OFFSET);299}300301public Symbol getFieldName(int index) {302int nameIndex = getFields().at(index * FIELD_SLOTS + NAME_INDEX_OFFSET);303if (index < getJavaFieldsCount()) {304return getConstants().getSymbolAt(nameIndex);305} else {306return vmSymbols.symbolAt(nameIndex);307}308}309310public short getFieldSignatureIndex(int index) {311if (index >= getJavaFieldsCount()) throw new IndexOutOfBoundsException("not a Java field;");312return getFields().at(index * FIELD_SLOTS + SIGNATURE_INDEX_OFFSET);313}314315public Symbol getFieldSignature(int index) {316int signatureIndex = getFields().at(index * FIELD_SLOTS + SIGNATURE_INDEX_OFFSET);317if (index < getJavaFieldsCount()) {318return getConstants().getSymbolAt(signatureIndex);319} else {320return vmSymbols.symbolAt(signatureIndex);321}322}323324public short getFieldGenericSignatureIndex(int index) {325// int len = getFields().length();326int allFieldsCount = getAllFieldsCount();327int generic_signature_slot = allFieldsCount * FIELD_SLOTS;328for (int i = 0; i < allFieldsCount; i++) {329short flags = getFieldAccessFlags(i);330AccessFlags access = new AccessFlags(flags);331if (i == index) {332if (access.fieldHasGenericSignature()) {333return getFields().at(generic_signature_slot);334} else {335return 0;336}337} else {338if (access.fieldHasGenericSignature()) {339generic_signature_slot ++;340}341}342}343return 0;344}345346public Symbol getFieldGenericSignature(int index) {347short genericSignatureIndex = getFieldGenericSignatureIndex(index);348if (genericSignatureIndex != 0) {349return getConstants().getSymbolAt(genericSignatureIndex);350}351return null;352}353354public short getFieldInitialValueIndex(int index) {355if (index >= getJavaFieldsCount()) throw new IndexOutOfBoundsException("not a Java field;");356return getFields().at(index * FIELD_SLOTS + INITVAL_INDEX_OFFSET);357}358359public int getFieldOffset(int index) {360U2Array fields = getFields();361short lo = fields.at(index * FIELD_SLOTS + LOW_OFFSET);362short hi = fields.at(index * FIELD_SLOTS + HIGH_OFFSET);363if ((lo & FIELDINFO_TAG_OFFSET) == FIELDINFO_TAG_OFFSET) {364return VM.getVM().buildIntFromShorts(lo, hi) >> FIELDINFO_TAG_SIZE;365}366throw new RuntimeException("should not reach here");367}368369// Accessors for declared fields370public Klass getArrayKlasses() { return (Klass) arrayKlasses.getValue(this); }371public MethodArray getMethods() { return new MethodArray(methods.getValue(getAddress())); }372373public MethodArray getDefaultMethods() {374if (defaultMethods != null) {375Address addr = defaultMethods.getValue(getAddress());376if ((addr != null) && (addr.getAddressAt(0) != null)) {377return new MethodArray(addr);378} else {379return null;380}381} else {382return null;383}384}385386public KlassArray getLocalInterfaces() { return new KlassArray(localInterfaces.getValue(getAddress())); }387public KlassArray getTransitiveInterfaces() { return new KlassArray(transitiveInterfaces.getValue(getAddress())); }388public int getJavaFieldsCount() { return (int) javaFieldsCount.getValue(this); }389public int getAllFieldsCount() {390int len = getFields().length();391int allFieldsCount = 0;392for (; allFieldsCount*FIELD_SLOTS < len; allFieldsCount++) {393short flags = getFieldAccessFlags(allFieldsCount);394AccessFlags access = new AccessFlags(flags);395if (access.fieldHasGenericSignature()) {396len --;397}398}399return allFieldsCount;400}401public ConstantPool getConstants() { return (ConstantPool) constants.getValue(this); }402public Symbol getSourceFileName() { return getConstants().getSourceFileName(); }403public String getSourceDebugExtension(){ return CStringUtilities.getString(sourceDebugExtension.getValue(getAddress())); }404public long getNonstaticFieldSize() { return nonstaticFieldSize.getValue(this); }405public long getStaticOopFieldCount() { return staticOopFieldCount.getValue(this); }406public long getNonstaticOopMapSize() { return nonstaticOopMapSize.getValue(this); }407public boolean getIsMarkedDependent() { return isMarkedDependent.getValue(this) != 0; }408public long getItableLen() { return itableLen.getValue(this); }409public long majorVersion() { return getConstants().majorVersion(); }410public long minorVersion() { return getConstants().minorVersion(); }411public Symbol getGenericSignature() { return getConstants().getGenericSignature(); }412413// "size helper" == instance size in words414public long getSizeHelper() {415int lh = getLayoutHelper();416if (Assert.ASSERTS_ENABLED) {417Assert.that(lh > 0, "layout helper initialized for instance class");418}419return lh / VM.getVM().getAddressSize();420}421422// same as enum InnerClassAttributeOffset in VM code.423private static class InnerClassAttributeOffset {424// from JVM spec. "InnerClasses" attribute425public static int innerClassInnerClassInfoOffset;426public static int innerClassOuterClassInfoOffset;427public static int innerClassInnerNameOffset;428public static int innerClassAccessFlagsOffset;429public static int innerClassNextOffset;430static {431VM.registerVMInitializedObserver(new Observer() {432public void update(Observable o, Object data) {433initialize(VM.getVM().getTypeDataBase());434}435});436}437438private static synchronized void initialize(TypeDataBase db) {439innerClassInnerClassInfoOffset = db.lookupIntConstant(440"InstanceKlass::inner_class_inner_class_info_offset").intValue();441innerClassOuterClassInfoOffset = db.lookupIntConstant(442"InstanceKlass::inner_class_outer_class_info_offset").intValue();443innerClassInnerNameOffset = db.lookupIntConstant(444"InstanceKlass::inner_class_inner_name_offset").intValue();445innerClassAccessFlagsOffset = db.lookupIntConstant(446"InstanceKlass::inner_class_access_flags_offset").intValue();447innerClassNextOffset = db.lookupIntConstant(448"InstanceKlass::inner_class_next_offset").intValue();449}450}451452private static class EnclosingMethodAttributeOffset {453public static int enclosingMethodAttributeSize;454static {455VM.registerVMInitializedObserver(new Observer() {456public void update(Observable o, Object data) {457initialize(VM.getVM().getTypeDataBase());458}459});460}461private static synchronized void initialize(TypeDataBase db) {462enclosingMethodAttributeSize = db.lookupIntConstant("InstanceKlass::enclosing_method_attribute_size").intValue();463}464}465466// refer to compute_modifier_flags in VM code.467public long computeModifierFlags() {468long access = getAccessFlags();469// But check if it happens to be member class.470U2Array innerClassList = getInnerClasses();471int length = (innerClassList == null)? 0 : (int) innerClassList.length();472if (length > 0) {473if (Assert.ASSERTS_ENABLED) {474Assert.that(length % InnerClassAttributeOffset.innerClassNextOffset == 0 ||475length % InnerClassAttributeOffset.innerClassNextOffset == EnclosingMethodAttributeOffset.enclosingMethodAttributeSize,476"just checking");477}478for (int i = 0; i < length; i += InnerClassAttributeOffset.innerClassNextOffset) {479if (i == length - EnclosingMethodAttributeOffset.enclosingMethodAttributeSize) {480break;481}482int ioff = innerClassList.at(i +483InnerClassAttributeOffset.innerClassInnerClassInfoOffset);484// 'ioff' can be zero.485// refer to JVM spec. section 4.7.5.486if (ioff != 0) {487// only look at classes that are already loaded488// since we are looking for the flags for our self.489Symbol name = getConstants().getKlassNameAt(ioff);490491if (name.equals(getName())) {492// This is really a member class493access = innerClassList.at(i +494InnerClassAttributeOffset.innerClassAccessFlagsOffset);495break;496}497}498} // for inner classes499}500501// Remember to strip ACC_SUPER bit502return (access & (~JVM_ACC_SUPER)) & JVM_ACC_WRITTEN_FLAGS;503}504505506// whether given Symbol is name of an inner/nested Klass of this Klass?507// anonymous and local classes are excluded.508public boolean isInnerClassName(Symbol sym) {509return isInInnerClasses(sym, false);510}511512// whether given Symbol is name of an inner/nested Klass of this Klass?513// anonymous classes excluded, but local classes are included.514public boolean isInnerOrLocalClassName(Symbol sym) {515return isInInnerClasses(sym, true);516}517518private boolean isInInnerClasses(Symbol sym, boolean includeLocals) {519U2Array innerClassList = getInnerClasses();520int length = ( innerClassList == null)? 0 : (int) innerClassList.length();521if (length > 0) {522if (Assert.ASSERTS_ENABLED) {523Assert.that(length % InnerClassAttributeOffset.innerClassNextOffset == 0 ||524length % InnerClassAttributeOffset.innerClassNextOffset == EnclosingMethodAttributeOffset.enclosingMethodAttributeSize,525"just checking");526}527for (int i = 0; i < length; i += InnerClassAttributeOffset.innerClassNextOffset) {528if (i == length - EnclosingMethodAttributeOffset.enclosingMethodAttributeSize) {529break;530}531int ioff = innerClassList.at(i +532InnerClassAttributeOffset.innerClassInnerClassInfoOffset);533// 'ioff' can be zero.534// refer to JVM spec. section 4.7.5.535if (ioff != 0) {536Symbol innerName = getConstants().getKlassNameAt(ioff);537Symbol myname = getName();538int ooff = innerClassList.at(i +539InnerClassAttributeOffset.innerClassOuterClassInfoOffset);540// for anonymous classes inner_name_index of InnerClasses541// attribute is zero.542int innerNameIndex = innerClassList.at(i +543InnerClassAttributeOffset.innerClassInnerNameOffset);544// if this is not a member (anonymous, local etc.), 'ooff' will be zero545// refer to JVM spec. section 4.7.5.546if (ooff == 0) {547if (includeLocals) {548// does it looks like my local class?549if (innerName.equals(sym) &&550innerName.asString().startsWith(myname.asString())) {551// exclude anonymous classes.552return (innerNameIndex != 0);553}554}555} else {556Symbol outerName = getConstants().getKlassNameAt(ooff);557558// include only if current class is outer class.559if (outerName.equals(myname) && innerName.equals(sym)) {560return true;561}562}563}564} // for inner classes565return false;566} else {567return false;568}569}570571public boolean implementsInterface(Klass k) {572if (Assert.ASSERTS_ENABLED) {573Assert.that(k.isInterface(), "should not reach here");574}575KlassArray interfaces = getTransitiveInterfaces();576final int len = interfaces.length();577for (int i = 0; i < len; i++) {578if (interfaces.getAt(i).equals(k)) return true;579}580return false;581}582583boolean computeSubtypeOf(Klass k) {584if (k.isInterface()) {585return implementsInterface(k);586} else {587return super.computeSubtypeOf(k);588}589}590591public void printValueOn(PrintStream tty) {592tty.print("InstanceKlass for " + getName().asString());593}594595public void iterateFields(MetadataVisitor visitor) {596super.iterateFields(visitor);597visitor.doMetadata(arrayKlasses, true);598// visitor.doOop(methods, true);599// visitor.doOop(localInterfaces, true);600// visitor.doOop(transitiveInterfaces, true);601visitor.doCInt(nonstaticFieldSize, true);602visitor.doCInt(staticFieldSize, true);603visitor.doCInt(staticOopFieldCount, true);604visitor.doCInt(nonstaticOopMapSize, true);605visitor.doCInt(isMarkedDependent, true);606visitor.doCInt(initState, true);607visitor.doCInt(itableLen, true);608}609610/*611* Visit the static fields of this InstanceKlass with the obj of612* the visitor set to the oop holding the fields, which is613* currently the java mirror.614*/615public void iterateStaticFields(OopVisitor visitor) {616visitor.setObj(getJavaMirror());617visitor.prologue();618iterateStaticFieldsInternal(visitor);619visitor.epilogue();620621}622623void iterateStaticFieldsInternal(OopVisitor visitor) {624int length = getJavaFieldsCount();625for (int index = 0; index < length; index++) {626short accessFlags = getFieldAccessFlags(index);627FieldType type = new FieldType(getFieldSignature(index));628AccessFlags access = new AccessFlags(accessFlags);629if (access.isStatic()) {630visitField(visitor, type, index);631}632}633}634635public Klass getJavaSuper() {636return getSuper();637}638639public static class StaticField {640public AccessFlags flags;641public Field field;642643StaticField(Field field, AccessFlags flags) {644this.field = field;645this.flags = flags;646}647}648649public Field[] getStaticFields() {650U2Array fields = getFields();651int length = getJavaFieldsCount();652ArrayList<Field> result = new ArrayList<>();653for (int index = 0; index < length; index++) {654Field f = newField(index);655if (f.isStatic()) {656result.add(f);657}658}659return result.toArray(new Field[result.size()]);660}661662public void iterateNonStaticFields(OopVisitor visitor, Oop obj) {663if (getSuper() != null) {664((InstanceKlass) getSuper()).iterateNonStaticFields(visitor, obj);665}666int length = getJavaFieldsCount();667for (int index = 0; index < length; index++) {668short accessFlags = getFieldAccessFlags(index);669FieldType type = new FieldType(getFieldSignature(index));670AccessFlags access = new AccessFlags(accessFlags);671if (!access.isStatic()) {672visitField(visitor, type, index);673}674}675}676677/** Field access by name. */678public Field findLocalField(String name, String sig) {679int length = getJavaFieldsCount();680for (int i = 0; i < length; i++) {681Symbol f_name = getFieldName(i);682Symbol f_sig = getFieldSignature(i);683if (f_name.equals(name) && f_sig.equals(sig)) {684return newField(i);685}686}687688return null;689}690691/** Find field in direct superinterfaces. */692public Field findInterfaceField(String name, String sig) {693KlassArray interfaces = getLocalInterfaces();694int n = interfaces.length();695for (int i = 0; i < n; i++) {696InstanceKlass intf1 = (InstanceKlass) interfaces.getAt(i);697if (Assert.ASSERTS_ENABLED) {698Assert.that(intf1.isInterface(), "just checking type");699}700// search for field in current interface701Field f = intf1.findLocalField(name, sig);702if (f != null) {703if (Assert.ASSERTS_ENABLED) {704Assert.that(f.getAccessFlagsObj().isStatic(), "interface field must be static");705}706return f;707}708// search for field in direct superinterfaces709f = intf1.findInterfaceField(name, sig);710if (f != null) return f;711}712// otherwise field lookup fails713return null;714}715716/** Find field according to JVM spec 5.4.3.2, returns the klass in717which the field is defined. */718public Field findField(String name, String sig) {719// search order according to newest JVM spec (5.4.3.2, p.167).720// 1) search for field in current klass721Field f = findLocalField(name, sig);722if (f != null) return f;723724// 2) search for field recursively in direct superinterfaces725f = findInterfaceField(name, sig);726if (f != null) return f;727728// 3) apply field lookup recursively if superclass exists729InstanceKlass supr = (InstanceKlass) getSuper();730if (supr != null) return supr.findField(name, sig);731732// 4) otherwise field lookup fails733return null;734}735736/** Find field according to JVM spec 5.4.3.2, returns the klass in737which the field is defined (retained only for backward738compatibility with jdbx) */739public Field findFieldDbg(String name, String sig) {740return findField(name, sig);741}742743/** Get field by its index in the fields array. Only designed for744use in a debugging system. */745public Field getFieldByIndex(int fieldIndex) {746return newField(fieldIndex);747}748749750/** Return a List of SA Fields for the fields declared in this class.751Inherited fields are not included.752Return an empty list if there are no fields declared in this class.753Only designed for use in a debugging system. */754public List<Field> getImmediateFields() {755// A list of Fields for each field declared in this class/interface,756// not including inherited fields.757int length = getJavaFieldsCount();758List<Field> immediateFields = new ArrayList<>(length);759for (int index = 0; index < length; index++) {760immediateFields.add(getFieldByIndex(index));761}762763return immediateFields;764}765766/** Return a List of SA Fields for all the java fields in this class,767including all inherited fields. This includes hidden768fields. Thus the returned list can contain fields with769the same name.770Return an empty list if there are no fields.771Only designed for use in a debugging system. */772public List<Field> getAllFields() {773// Contains a Field for each field in this class, including immediate774// fields and inherited fields.775List<Field> allFields = getImmediateFields();776777// transitiveInterfaces contains all interfaces implemented778// by this class and its superclass chain with no duplicates.779780KlassArray interfaces = getTransitiveInterfaces();781int n = interfaces.length();782for (int i = 0; i < n; i++) {783InstanceKlass intf1 = (InstanceKlass) interfaces.getAt(i);784if (Assert.ASSERTS_ENABLED) {785Assert.that(intf1.isInterface(), "just checking type");786}787allFields.addAll(intf1.getImmediateFields());788}789790// Get all fields in the superclass, recursively. But, don't791// include fields in interfaces implemented by superclasses;792// we already have all those.793if (!isInterface()) {794InstanceKlass supr;795if ( (supr = (InstanceKlass) getSuper()) != null) {796allFields.addAll(supr.getImmediateFields());797}798}799800return allFields;801}802803804/** Return a List of SA Methods declared directly in this class/interface.805Return an empty list if there are none, or if this isn't a class/806interface.807*/808public List<Method> getImmediateMethods() {809// Contains a Method for each method declared in this class/interface810// not including inherited methods.811812MethodArray methods = getMethods();813int length = methods.length();814Method[] tmp = new Method[length];815816IntArray methodOrdering = getMethodOrdering();817if (methodOrdering.length() != length) {818// no ordering info present819for (int index = 0; index < length; index++) {820tmp[index] = methods.at(index);821}822} else {823for (int index = 0; index < length; index++) {824int originalIndex = methodOrdering.at(index);825tmp[originalIndex] = methods.at(index);826}827}828829return Arrays.asList(tmp);830}831832/** Return a List containing an SA InstanceKlass for each833interface named in this class's 'implements' clause.834*/835public List<Klass> getDirectImplementedInterfaces() {836// Contains an InstanceKlass for each interface in this classes837// 'implements' clause.838839KlassArray interfaces = getLocalInterfaces();840int length = interfaces.length();841List<Klass> directImplementedInterfaces = new ArrayList<>(length);842843for (int index = 0; index < length; index ++) {844directImplementedInterfaces.add(interfaces.getAt(index));845}846847return directImplementedInterfaces;848}849850public Klass arrayKlassImpl(boolean orNull, int n) {851// FIXME: in reflective system this would need to change to852// actually allocate853if (getArrayKlasses() == null) { return null; }854ObjArrayKlass oak = (ObjArrayKlass) getArrayKlasses();855if (orNull) {856return oak.arrayKlassOrNull(n);857}858return oak.arrayKlass(n);859}860861public Klass arrayKlassImpl(boolean orNull) {862return arrayKlassImpl(orNull, 1);863}864865public String signature() {866return "L" + super.signature() + ";";867}868869/** Find method in vtable. */870public Method findMethod(String name, String sig) {871return findMethod(getMethods(), name, sig);872}873874/** Breakpoint support (see methods on Method* for details) */875public BreakpointInfo getBreakpoints() {876if (!VM.getVM().isJvmtiSupported()) {877return null;878}879Address addr = getAddress().getAddressAt(breakpoints.getOffset());880return (BreakpointInfo) VMObjectFactory.newObject(BreakpointInfo.class, addr);881}882883public IntArray getMethodOrdering() {884Address addr = getAddress().getAddressAt(methodOrdering.getOffset());885return (IntArray) VMObjectFactory.newObject(IntArray.class, addr);886}887888public U2Array getFields() {889Address addr = getAddress().getAddressAt(fields.getOffset());890return (U2Array) VMObjectFactory.newObject(U2Array.class, addr);891}892893public U2Array getInnerClasses() {894Address addr = getAddress().getAddressAt(innerClasses.getOffset());895return (U2Array) VMObjectFactory.newObject(U2Array.class, addr);896}897898899//----------------------------------------------------------------------900// Internals only below this point901//902903private void visitField(OopVisitor visitor, FieldType type, int index) {904Field f = newField(index);905if (type.isOop()) {906visitor.doOop((OopField) f, false);907return;908}909if (type.isByte()) {910visitor.doByte((ByteField) f, false);911return;912}913if (type.isChar()) {914visitor.doChar((CharField) f, false);915return;916}917if (type.isDouble()) {918visitor.doDouble((DoubleField) f, false);919return;920}921if (type.isFloat()) {922visitor.doFloat((FloatField) f, false);923return;924}925if (type.isInt()) {926visitor.doInt((IntField) f, false);927return;928}929if (type.isLong()) {930visitor.doLong((LongField) f, false);931return;932}933if (type.isShort()) {934visitor.doShort((ShortField) f, false);935return;936}937if (type.isBoolean()) {938visitor.doBoolean((BooleanField) f, false);939return;940}941}942943// Creates new field from index in fields TypeArray944private Field newField(int index) {945FieldType type = new FieldType(getFieldSignature(index));946if (type.isOop()) {947if (VM.getVM().isCompressedOopsEnabled()) {948return new NarrowOopField(this, index);949} else {950return new OopField(this, index);951}952}953if (type.isByte()) {954return new ByteField(this, index);955}956if (type.isChar()) {957return new CharField(this, index);958}959if (type.isDouble()) {960return new DoubleField(this, index);961}962if (type.isFloat()) {963return new FloatField(this, index);964}965if (type.isInt()) {966return new IntField(this, index);967}968if (type.isLong()) {969return new LongField(this, index);970}971if (type.isShort()) {972return new ShortField(this, index);973}974if (type.isBoolean()) {975return new BooleanField(this, index);976}977throw new RuntimeException("Illegal field type at index " + index);978}979980private static Method findMethod(MethodArray methods, String name, String signature) {981int index = linearSearch(methods, name, signature);982if (index != -1) {983return methods.at(index);984} else {985return null;986}987}988989private static int linearSearch(MethodArray methods, String name, String signature) {990int len = (int) methods.length();991for (int index = 0; index < len; index++) {992Method m = methods.at(index);993if (m.getSignature().equals(signature) && m.getName().equals(name)) {994return index;995}996}997return -1;998}9991000public void dumpReplayData(PrintStream out) {1001ConstantPool cp = getConstants();10021003// Try to record related loaded classes1004Klass sub = getSubklassKlass();1005while (sub != null) {1006if (sub instanceof InstanceKlass) {1007out.println("instanceKlass " + sub.getName().asString());1008}1009sub = sub.getNextSiblingKlass();1010}10111012final int length = (int) cp.getLength();1013out.print("ciInstanceKlass " + getName().asString() + " " + (isLinked() ? 1 : 0) + " " + (isInitialized() ? 1 : 0) + " " + length);1014for (int index = 1; index < length; index++) {1015out.print(" " + cp.getTags().at(index));1016}1017out.println();1018if (isInitialized()) {1019Field[] staticFields = getStaticFields();1020for (int i = 0; i < staticFields.length; i++) {1021Field f = staticFields[i];1022Oop mirror = getJavaMirror();1023if (f.isFinal() && !f.hasInitialValue()) {1024out.print("staticfield " + getName().asString() + " " +1025OopUtilities.escapeString(f.getID().getName()) + " " +1026f.getFieldType().getSignature().asString() + " ");1027if (f instanceof ByteField) {1028ByteField bf = (ByteField)f;1029out.println(bf.getValue(mirror));1030} else if (f instanceof BooleanField) {1031BooleanField bf = (BooleanField)f;1032out.println(bf.getValue(mirror) ? 1 : 0);1033} else if (f instanceof ShortField) {1034ShortField bf = (ShortField)f;1035out.println(bf.getValue(mirror));1036} else if (f instanceof CharField) {1037CharField bf = (CharField)f;1038out.println(bf.getValue(mirror) & 0xffff);1039} else if (f instanceof IntField) {1040IntField bf = (IntField)f;1041out.println(bf.getValue(mirror));1042} else if (f instanceof LongField) {1043LongField bf = (LongField)f;1044out.println(bf.getValue(mirror));1045} else if (f instanceof FloatField) {1046FloatField bf = (FloatField)f;1047out.println(Float.floatToRawIntBits(bf.getValue(mirror)));1048} else if (f instanceof DoubleField) {1049DoubleField bf = (DoubleField)f;1050out.println(Double.doubleToRawLongBits(bf.getValue(mirror)));1051} else if (f instanceof OopField) {1052OopField bf = (OopField)f;10531054Oop value = bf.getValue(mirror);1055if (value == null) {1056out.println("null");1057} else if (value.isInstance()) {1058Instance inst = (Instance)value;1059if (inst.isA(SystemDictionary.getStringKlass())) {1060out.println("\"" + OopUtilities.stringOopToEscapedString(inst) + "\"");1061} else {1062out.println(inst.getKlass().getName().asString());1063}1064} else if (value.isObjArray()) {1065ObjArray oa = (ObjArray)value;1066Klass ek = (ObjArrayKlass)oa.getKlass();1067out.println(oa.getLength() + " " + ek.getName().asString());1068} else if (value.isTypeArray()) {1069TypeArray ta = (TypeArray)value;1070out.println(ta.getLength());1071} else {1072out.println(value);1073}1074}1075}1076}1077}1078}1079}108010811082