1 /* 2 * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 package sun.jvm.hotspot.oops; 26 27 import java.io.*; 28 import java.util.*; 29 import sun.jvm.hotspot.classfile.ClassLoaderData; 30 import sun.jvm.hotspot.debugger.*; 31 import sun.jvm.hotspot.memory.*; 32 import sun.jvm.hotspot.memory.Dictionary; 33 import sun.jvm.hotspot.runtime.*; 34 import sun.jvm.hotspot.types.*; 35 import sun.jvm.hotspot.utilities.*; 36 import sun.jvm.hotspot.utilities.Observable; 37 import sun.jvm.hotspot.utilities.Observer; 38 39 // An InstanceKlass is the VM level representation of a Java class. 40 41 public class InstanceKlass extends Klass { 42 static { VM.registerVMInitializedObserver(new Observer() { public void update(Observable o, Object data) { initialize(VM.getVM().getTypeDataBase()); } })43 VM.registerVMInitializedObserver(new Observer() { 44 public void update(Observable o, Object data) { 45 initialize(VM.getVM().getTypeDataBase()); 46 } 47 }); 48 } 49 50 // field offset constants 51 private static int ACCESS_FLAGS_OFFSET; 52 private static int NAME_INDEX_OFFSET; 53 private static int SIGNATURE_INDEX_OFFSET; 54 private static int INITVAL_INDEX_OFFSET; 55 private static int LOW_OFFSET; 56 private static int HIGH_OFFSET; 57 private static int FIELD_SLOTS; 58 private static short FIELDINFO_TAG_SIZE; 59 private static short FIELDINFO_TAG_MASK; 60 private static short FIELDINFO_TAG_OFFSET; 61 62 // ClassState constants 63 private static int CLASS_STATE_ALLOCATED; 64 private static int CLASS_STATE_LOADED; 65 private static int CLASS_STATE_LINKED; 66 private static int CLASS_STATE_BEING_INITIALIZED; 67 private static int CLASS_STATE_FULLY_INITIALIZED; 68 private static int CLASS_STATE_INITIALIZATION_ERROR; 69 70 // _misc_flags constants 71 private static int MISC_REWRITTEN; 72 private static int MISC_HAS_NONSTATIC_FIELDS; 73 private static int MISC_SHOULD_VERIFY_CLASS; 74 private static int MISC_IS_UNSAFE_ANONYMOUS; 75 private static int MISC_IS_CONTENDED; 76 private static int MISC_HAS_NONSTATIC_CONCRETE_METHODS; 77 private static int MISC_DECLARES_NONSTATIC_CONCRETE_METHODS; 78 private static int MISC_HAS_BEEN_REDEFINED; 79 private static int MISC_HAS_PASSED_FINGERPRINT_CHECK; 80 private static int MISC_IS_SCRATCH_CLASS; 81 private static int MISC_IS_SHARED_BOOT_CLASS; 82 private static int MISC_IS_SHARED_PLATFORM_CLASS; 83 private static int MISC_IS_SHARED_APP_CLASS; 84 initialize(TypeDataBase db)85 private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { 86 Type type = db.lookupType("InstanceKlass"); 87 arrayKlasses = new MetadataField(type.getAddressField("_array_klasses"), 0); 88 methods = type.getAddressField("_methods"); 89 defaultMethods = type.getAddressField("_default_methods"); 90 methodOrdering = type.getAddressField("_method_ordering"); 91 localInterfaces = type.getAddressField("_local_interfaces"); 92 transitiveInterfaces = type.getAddressField("_transitive_interfaces"); 93 fields = type.getAddressField("_fields"); 94 javaFieldsCount = new CIntField(type.getCIntegerField("_java_fields_count"), 0); 95 constants = new MetadataField(type.getAddressField("_constants"), 0); 96 sourceDebugExtension = type.getAddressField("_source_debug_extension"); 97 innerClasses = type.getAddressField("_inner_classes"); 98 nonstaticFieldSize = new CIntField(type.getCIntegerField("_nonstatic_field_size"), 0); 99 staticFieldSize = new CIntField(type.getCIntegerField("_static_field_size"), 0); 100 staticOopFieldCount = new CIntField(type.getCIntegerField("_static_oop_field_count"), 0); 101 nonstaticOopMapSize = new CIntField(type.getCIntegerField("_nonstatic_oop_map_size"), 0); 102 isMarkedDependent = new CIntField(type.getCIntegerField("_is_marked_dependent"), 0); 103 initState = new CIntField(type.getCIntegerField("_init_state"), 0); 104 itableLen = new CIntField(type.getCIntegerField("_itable_len"), 0); 105 if (VM.getVM().isJvmtiSupported()) { 106 breakpoints = type.getAddressField("_breakpoints"); 107 } 108 miscFlags = new CIntField(type.getCIntegerField("_misc_flags"), 0); 109 headerSize = type.getSize(); 110 111 // read field offset constants 112 ACCESS_FLAGS_OFFSET = db.lookupIntConstant("FieldInfo::access_flags_offset").intValue(); 113 NAME_INDEX_OFFSET = db.lookupIntConstant("FieldInfo::name_index_offset").intValue(); 114 SIGNATURE_INDEX_OFFSET = db.lookupIntConstant("FieldInfo::signature_index_offset").intValue(); 115 INITVAL_INDEX_OFFSET = db.lookupIntConstant("FieldInfo::initval_index_offset").intValue(); 116 LOW_OFFSET = db.lookupIntConstant("FieldInfo::low_packed_offset").intValue(); 117 HIGH_OFFSET = db.lookupIntConstant("FieldInfo::high_packed_offset").intValue(); 118 FIELD_SLOTS = db.lookupIntConstant("FieldInfo::field_slots").intValue(); 119 FIELDINFO_TAG_SIZE = db.lookupIntConstant("FIELDINFO_TAG_SIZE").shortValue(); 120 FIELDINFO_TAG_MASK = db.lookupIntConstant("FIELDINFO_TAG_MASK").shortValue(); 121 FIELDINFO_TAG_OFFSET = db.lookupIntConstant("FIELDINFO_TAG_OFFSET").shortValue(); 122 123 // read ClassState constants 124 CLASS_STATE_ALLOCATED = db.lookupIntConstant("InstanceKlass::allocated").intValue(); 125 CLASS_STATE_LOADED = db.lookupIntConstant("InstanceKlass::loaded").intValue(); 126 CLASS_STATE_LINKED = db.lookupIntConstant("InstanceKlass::linked").intValue(); 127 CLASS_STATE_BEING_INITIALIZED = db.lookupIntConstant("InstanceKlass::being_initialized").intValue(); 128 CLASS_STATE_FULLY_INITIALIZED = db.lookupIntConstant("InstanceKlass::fully_initialized").intValue(); 129 CLASS_STATE_INITIALIZATION_ERROR = db.lookupIntConstant("InstanceKlass::initialization_error").intValue(); 130 131 MISC_REWRITTEN = db.lookupIntConstant("InstanceKlass::_misc_rewritten").intValue(); 132 MISC_HAS_NONSTATIC_FIELDS = db.lookupIntConstant("InstanceKlass::_misc_has_nonstatic_fields").intValue(); 133 MISC_SHOULD_VERIFY_CLASS = db.lookupIntConstant("InstanceKlass::_misc_should_verify_class").intValue(); 134 MISC_IS_UNSAFE_ANONYMOUS = db.lookupIntConstant("InstanceKlass::_misc_is_unsafe_anonymous").intValue(); 135 MISC_IS_CONTENDED = db.lookupIntConstant("InstanceKlass::_misc_is_contended").intValue(); 136 MISC_HAS_NONSTATIC_CONCRETE_METHODS = db.lookupIntConstant("InstanceKlass::_misc_has_nonstatic_concrete_methods").intValue(); 137 MISC_DECLARES_NONSTATIC_CONCRETE_METHODS = db.lookupIntConstant("InstanceKlass::_misc_declares_nonstatic_concrete_methods").intValue(); 138 MISC_HAS_BEEN_REDEFINED = db.lookupIntConstant("InstanceKlass::_misc_has_been_redefined").intValue(); 139 MISC_HAS_PASSED_FINGERPRINT_CHECK = db.lookupIntConstant("InstanceKlass::_misc_has_passed_fingerprint_check").intValue(); 140 MISC_IS_SCRATCH_CLASS = db.lookupIntConstant("InstanceKlass::_misc_is_scratch_class").intValue(); 141 MISC_IS_SHARED_BOOT_CLASS = db.lookupIntConstant("InstanceKlass::_misc_is_shared_boot_class").intValue(); 142 MISC_IS_SHARED_PLATFORM_CLASS = db.lookupIntConstant("InstanceKlass::_misc_is_shared_platform_class").intValue(); 143 MISC_IS_SHARED_APP_CLASS = db.lookupIntConstant("InstanceKlass::_misc_is_shared_app_class").intValue(); 144 } 145 InstanceKlass(Address addr)146 public InstanceKlass(Address addr) { 147 super(addr); 148 149 // If the class hasn't yet reached the "loaded" init state, then don't go any further 150 // or we'll run into problems trying to look at fields that are not yet setup. 151 // Attempted lookups of this InstanceKlass via ClassLoaderDataGraph, ClassLoaderData, 152 // and Dictionary will all refuse to return it. The main purpose of allowing this 153 // InstanceKlass to initialize is so ClassLoaderData.getKlasses() will succeed, allowing 154 // ClassLoaderData.classesDo() to iterate over all Klasses (skipping those that are 155 // not yet fully loaded). 156 if (!isLoaded()) { 157 return; 158 } 159 160 if (getJavaFieldsCount() != getAllFieldsCount()) { 161 // Exercise the injected field logic 162 for (int i = getJavaFieldsCount(); i < getAllFieldsCount(); i++) { 163 getFieldName(i); 164 getFieldSignature(i); 165 } 166 } 167 } 168 169 private static MetadataField arrayKlasses; 170 private static AddressField methods; 171 private static AddressField defaultMethods; 172 private static AddressField methodOrdering; 173 private static AddressField localInterfaces; 174 private static AddressField transitiveInterfaces; 175 private static AddressField fields; 176 private static CIntField javaFieldsCount; 177 private static MetadataField constants; 178 private static AddressField sourceDebugExtension; 179 private static AddressField innerClasses; 180 private static CIntField nonstaticFieldSize; 181 private static CIntField staticFieldSize; 182 private static CIntField staticOopFieldCount; 183 private static CIntField nonstaticOopMapSize; 184 private static CIntField isMarkedDependent; 185 private static CIntField initState; 186 private static CIntField itableLen; 187 private static AddressField breakpoints; 188 private static CIntField miscFlags; 189 190 // type safe enum for ClassState from instanceKlass.hpp 191 public static class ClassState { 192 public static final ClassState ALLOCATED = new ClassState("allocated"); 193 public static final ClassState LOADED = new ClassState("loaded"); 194 public static final ClassState LINKED = new ClassState("linked"); 195 public static final ClassState BEING_INITIALIZED = new ClassState("beingInitialized"); 196 public static final ClassState FULLY_INITIALIZED = new ClassState("fullyInitialized"); 197 public static final ClassState INITIALIZATION_ERROR = new ClassState("initializationError"); 198 ClassState(String value)199 private ClassState(String value) { 200 this.value = value; 201 } 202 toString()203 public String toString() { 204 return value; 205 } 206 207 private String value; 208 } 209 getInitStateAsInt()210 public int getInitStateAsInt() { return (int) initState.getValue(this); } getInitState()211 public ClassState getInitState() { 212 int state = getInitStateAsInt(); 213 if (state == CLASS_STATE_ALLOCATED) { 214 return ClassState.ALLOCATED; 215 } else if (state == CLASS_STATE_LOADED) { 216 return ClassState.LOADED; 217 } else if (state == CLASS_STATE_LINKED) { 218 return ClassState.LINKED; 219 } else if (state == CLASS_STATE_BEING_INITIALIZED) { 220 return ClassState.BEING_INITIALIZED; 221 } else if (state == CLASS_STATE_FULLY_INITIALIZED) { 222 return ClassState.FULLY_INITIALIZED; 223 } else if (state == CLASS_STATE_INITIALIZATION_ERROR) { 224 return ClassState.INITIALIZATION_ERROR; 225 } else { 226 throw new RuntimeException("should not reach here"); 227 } 228 } 229 230 // initialization state quaries isLoaded()231 public boolean isLoaded() { 232 return getInitStateAsInt() >= CLASS_STATE_LOADED; 233 } 234 isLinked()235 public boolean isLinked() { 236 return getInitStateAsInt() >= CLASS_STATE_LINKED; 237 } 238 isInitialized()239 public boolean isInitialized() { 240 return getInitStateAsInt() == CLASS_STATE_FULLY_INITIALIZED; 241 } 242 isNotInitialized()243 public boolean isNotInitialized() { 244 return getInitStateAsInt() < CLASS_STATE_BEING_INITIALIZED; 245 } 246 isBeingInitialized()247 public boolean isBeingInitialized() { 248 return getInitStateAsInt() == CLASS_STATE_BEING_INITIALIZED; 249 } 250 isInErrorState()251 public boolean isInErrorState() { 252 return getInitStateAsInt() == CLASS_STATE_INITIALIZATION_ERROR; 253 } 254 getClassStatus()255 public int getClassStatus() { 256 int result = 0; 257 if (isLinked()) { 258 result |= JVMDIClassStatus.VERIFIED | JVMDIClassStatus.PREPARED; 259 } 260 261 if (isInitialized()) { 262 if (Assert.ASSERTS_ENABLED) { 263 Assert.that(isLinked(), "Class status is not consistent"); 264 } 265 result |= JVMDIClassStatus.INITIALIZED; 266 } 267 268 if (isInErrorState()) { 269 result |= JVMDIClassStatus.ERROR; 270 } 271 return result; 272 } 273 274 // Byteside of the header 275 private static long headerSize; 276 getObjectSize(Oop object)277 public long getObjectSize(Oop object) { 278 return getSizeHelper() * VM.getVM().getAddressSize(); 279 } 280 getSize()281 public long getSize() { // in number of bytes 282 long wordLength = VM.getVM().getBytesPerWord(); 283 long size = getHeaderSize() + 284 (getVtableLen() + 285 getItableLen() + 286 getNonstaticOopMapSize()) * wordLength; 287 if (isInterface()) { 288 size += wordLength; 289 } 290 if (isUnsafeAnonymous()) { 291 size += wordLength; 292 } 293 if (hasStoredFingerprint()) { 294 size += 8; // uint64_t 295 } 296 return alignSize(size); 297 } 298 getMiscFlags()299 private int getMiscFlags() { 300 return (int) miscFlags.getValue(this); 301 } 302 isUnsafeAnonymous()303 public boolean isUnsafeAnonymous() { 304 return (getMiscFlags() & MISC_IS_UNSAFE_ANONYMOUS) != 0; 305 } 306 shouldStoreFingerprint()307 public static boolean shouldStoreFingerprint() { 308 VM vm = VM.getVM(); 309 if (vm.getCommandLineBooleanFlag("EnableJVMCI") && !vm.getCommandLineBooleanFlag("UseJVMCICompiler")) { 310 return true; 311 } 312 if (vm.getCommandLineBooleanFlag("DumpSharedSpaces")) { 313 return true; 314 } 315 return false; 316 } 317 hasStoredFingerprint()318 public boolean hasStoredFingerprint() { 319 return shouldStoreFingerprint() || isShared(); 320 } 321 getHeaderSize()322 public static long getHeaderSize() { return headerSize; } 323 getFieldAccessFlags(int index)324 public short getFieldAccessFlags(int index) { 325 return getFields().at(index * FIELD_SLOTS + ACCESS_FLAGS_OFFSET); 326 } 327 getFieldNameIndex(int index)328 public short getFieldNameIndex(int index) { 329 if (index >= getJavaFieldsCount()) throw new IndexOutOfBoundsException("not a Java field;"); 330 return getFields().at(index * FIELD_SLOTS + NAME_INDEX_OFFSET); 331 } 332 getFieldName(int index)333 public Symbol getFieldName(int index) { 334 int nameIndex = getFields().at(index * FIELD_SLOTS + NAME_INDEX_OFFSET); 335 if (index < getJavaFieldsCount()) { 336 return getConstants().getSymbolAt(nameIndex); 337 } else { 338 return vmSymbols.symbolAt(nameIndex); 339 } 340 } 341 getFieldSignatureIndex(int index)342 public short getFieldSignatureIndex(int index) { 343 if (index >= getJavaFieldsCount()) throw new IndexOutOfBoundsException("not a Java field;"); 344 return getFields().at(index * FIELD_SLOTS + SIGNATURE_INDEX_OFFSET); 345 } 346 getFieldSignature(int index)347 public Symbol getFieldSignature(int index) { 348 int signatureIndex = getFields().at(index * FIELD_SLOTS + SIGNATURE_INDEX_OFFSET); 349 if (index < getJavaFieldsCount()) { 350 return getConstants().getSymbolAt(signatureIndex); 351 } else { 352 return vmSymbols.symbolAt(signatureIndex); 353 } 354 } 355 getFieldGenericSignatureIndex(int index)356 public short getFieldGenericSignatureIndex(int index) { 357 // int len = getFields().length(); 358 int allFieldsCount = getAllFieldsCount(); 359 int generic_signature_slot = allFieldsCount * FIELD_SLOTS; 360 for (int i = 0; i < allFieldsCount; i++) { 361 short flags = getFieldAccessFlags(i); 362 AccessFlags access = new AccessFlags(flags); 363 if (i == index) { 364 if (access.fieldHasGenericSignature()) { 365 return getFields().at(generic_signature_slot); 366 } else { 367 return 0; 368 } 369 } else { 370 if (access.fieldHasGenericSignature()) { 371 generic_signature_slot ++; 372 } 373 } 374 } 375 return 0; 376 } 377 getFieldGenericSignature(int index)378 public Symbol getFieldGenericSignature(int index) { 379 short genericSignatureIndex = getFieldGenericSignatureIndex(index); 380 if (genericSignatureIndex != 0) { 381 return getConstants().getSymbolAt(genericSignatureIndex); 382 } 383 return null; 384 } 385 getFieldInitialValueIndex(int index)386 public short getFieldInitialValueIndex(int index) { 387 if (index >= getJavaFieldsCount()) throw new IndexOutOfBoundsException("not a Java field;"); 388 return getFields().at(index * FIELD_SLOTS + INITVAL_INDEX_OFFSET); 389 } 390 getFieldOffset(int index)391 public int getFieldOffset(int index) { 392 U2Array fields = getFields(); 393 short lo = fields.at(index * FIELD_SLOTS + LOW_OFFSET); 394 short hi = fields.at(index * FIELD_SLOTS + HIGH_OFFSET); 395 if ((lo & FIELDINFO_TAG_MASK) == FIELDINFO_TAG_OFFSET) { 396 return VM.getVM().buildIntFromShorts(lo, hi) >> FIELDINFO_TAG_SIZE; 397 } 398 throw new RuntimeException("should not reach here"); 399 } 400 401 // Accessors for declared fields getArrayKlasses()402 public Klass getArrayKlasses() { return (Klass) arrayKlasses.getValue(this); } getMethods()403 public MethodArray getMethods() { return new MethodArray(methods.getValue(getAddress())); } 404 getDefaultMethods()405 public MethodArray getDefaultMethods() { 406 if (defaultMethods != null) { 407 Address addr = defaultMethods.getValue(getAddress()); 408 if ((addr != null) && (addr.getAddressAt(0) != null)) { 409 return new MethodArray(addr); 410 } else { 411 return null; 412 } 413 } else { 414 return null; 415 } 416 } 417 getLocalInterfaces()418 public KlassArray getLocalInterfaces() { return new KlassArray(localInterfaces.getValue(getAddress())); } getTransitiveInterfaces()419 public KlassArray getTransitiveInterfaces() { return new KlassArray(transitiveInterfaces.getValue(getAddress())); } getJavaFieldsCount()420 public int getJavaFieldsCount() { return (int) javaFieldsCount.getValue(this); } getAllFieldsCount()421 public int getAllFieldsCount() { 422 int len = getFields().length(); 423 int allFieldsCount = 0; 424 for (; allFieldsCount*FIELD_SLOTS < len; allFieldsCount++) { 425 short flags = getFieldAccessFlags(allFieldsCount); 426 AccessFlags access = new AccessFlags(flags); 427 if (access.fieldHasGenericSignature()) { 428 len --; 429 } 430 } 431 return allFieldsCount; 432 } getConstants()433 public ConstantPool getConstants() { return (ConstantPool) constants.getValue(this); } getSourceFileName()434 public Symbol getSourceFileName() { return getConstants().getSourceFileName(); } getSourceDebugExtension()435 public String getSourceDebugExtension(){ return CStringUtilities.getString(sourceDebugExtension.getValue(getAddress())); } getNonstaticFieldSize()436 public long getNonstaticFieldSize() { return nonstaticFieldSize.getValue(this); } getStaticOopFieldCount()437 public long getStaticOopFieldCount() { return staticOopFieldCount.getValue(this); } getNonstaticOopMapSize()438 public long getNonstaticOopMapSize() { return nonstaticOopMapSize.getValue(this); } getIsMarkedDependent()439 public boolean getIsMarkedDependent() { return isMarkedDependent.getValue(this) != 0; } getItableLen()440 public long getItableLen() { return itableLen.getValue(this); } majorVersion()441 public long majorVersion() { return getConstants().majorVersion(); } minorVersion()442 public long minorVersion() { return getConstants().minorVersion(); } getGenericSignature()443 public Symbol getGenericSignature() { return getConstants().getGenericSignature(); } 444 445 // "size helper" == instance size in words getSizeHelper()446 public long getSizeHelper() { 447 int lh = getLayoutHelper(); 448 if (Assert.ASSERTS_ENABLED) { 449 Assert.that(lh > 0, "layout helper initialized for instance class"); 450 } 451 return lh / VM.getVM().getAddressSize(); 452 } 453 454 // same as enum InnerClassAttributeOffset in VM code. 455 private static class InnerClassAttributeOffset { 456 // from JVM spec. "InnerClasses" attribute 457 public static int innerClassInnerClassInfoOffset; 458 public static int innerClassOuterClassInfoOffset; 459 public static int innerClassInnerNameOffset; 460 public static int innerClassAccessFlagsOffset; 461 public static int innerClassNextOffset; 462 static { VM.registerVMInitializedObserver(new Observer() { public void update(Observable o, Object data) { initialize(VM.getVM().getTypeDataBase()); } })463 VM.registerVMInitializedObserver(new Observer() { 464 public void update(Observable o, Object data) { 465 initialize(VM.getVM().getTypeDataBase()); 466 } 467 }); 468 } 469 initialize(TypeDataBase db)470 private static synchronized void initialize(TypeDataBase db) { 471 innerClassInnerClassInfoOffset = db.lookupIntConstant( 472 "InstanceKlass::inner_class_inner_class_info_offset").intValue(); 473 innerClassOuterClassInfoOffset = db.lookupIntConstant( 474 "InstanceKlass::inner_class_outer_class_info_offset").intValue(); 475 innerClassInnerNameOffset = db.lookupIntConstant( 476 "InstanceKlass::inner_class_inner_name_offset").intValue(); 477 innerClassAccessFlagsOffset = db.lookupIntConstant( 478 "InstanceKlass::inner_class_access_flags_offset").intValue(); 479 innerClassNextOffset = db.lookupIntConstant( 480 "InstanceKlass::inner_class_next_offset").intValue(); 481 } 482 } 483 484 private static class EnclosingMethodAttributeOffset { 485 public static int enclosingMethodAttributeSize; 486 static { VM.registerVMInitializedObserver(new Observer() { public void update(Observable o, Object data) { initialize(VM.getVM().getTypeDataBase()); } })487 VM.registerVMInitializedObserver(new Observer() { 488 public void update(Observable o, Object data) { 489 initialize(VM.getVM().getTypeDataBase()); 490 } 491 }); 492 } initialize(TypeDataBase db)493 private static synchronized void initialize(TypeDataBase db) { 494 enclosingMethodAttributeSize = db.lookupIntConstant("InstanceKlass::enclosing_method_attribute_size").intValue(); 495 } 496 } 497 498 // refer to compute_modifier_flags in VM code. computeModifierFlags()499 public long computeModifierFlags() { 500 long access = getAccessFlags(); 501 // But check if it happens to be member class. 502 U2Array innerClassList = getInnerClasses(); 503 int length = (innerClassList == null)? 0 : (int) innerClassList.length(); 504 if (length > 0) { 505 if (Assert.ASSERTS_ENABLED) { 506 Assert.that(length % InnerClassAttributeOffset.innerClassNextOffset == 0 || 507 length % InnerClassAttributeOffset.innerClassNextOffset == EnclosingMethodAttributeOffset.enclosingMethodAttributeSize, 508 "just checking"); 509 } 510 for (int i = 0; i < length; i += InnerClassAttributeOffset.innerClassNextOffset) { 511 if (i == length - EnclosingMethodAttributeOffset.enclosingMethodAttributeSize) { 512 break; 513 } 514 int ioff = innerClassList.at(i + 515 InnerClassAttributeOffset.innerClassInnerClassInfoOffset); 516 // 'ioff' can be zero. 517 // refer to JVM spec. section 4.7.5. 518 if (ioff != 0) { 519 // only look at classes that are already loaded 520 // since we are looking for the flags for our self. 521 Symbol name = getConstants().getKlassNameAt(ioff); 522 523 if (name.equals(getName())) { 524 // This is really a member class 525 access = innerClassList.at(i + 526 InnerClassAttributeOffset.innerClassAccessFlagsOffset); 527 break; 528 } 529 } 530 } // for inner classes 531 } 532 533 // Remember to strip ACC_SUPER bit 534 return (access & (~JVM_ACC_SUPER)) & JVM_ACC_WRITTEN_FLAGS; 535 } 536 537 538 // whether given Symbol is name of an inner/nested Klass of this Klass? 539 // anonymous and local classes are excluded. isInnerClassName(Symbol sym)540 public boolean isInnerClassName(Symbol sym) { 541 return isInInnerClasses(sym, false); 542 } 543 544 // whether given Symbol is name of an inner/nested Klass of this Klass? 545 // anonymous classes excluded, but local classes are included. isInnerOrLocalClassName(Symbol sym)546 public boolean isInnerOrLocalClassName(Symbol sym) { 547 return isInInnerClasses(sym, true); 548 } 549 isInInnerClasses(Symbol sym, boolean includeLocals)550 private boolean isInInnerClasses(Symbol sym, boolean includeLocals) { 551 U2Array innerClassList = getInnerClasses(); 552 int length = ( innerClassList == null)? 0 : (int) innerClassList.length(); 553 if (length > 0) { 554 if (Assert.ASSERTS_ENABLED) { 555 Assert.that(length % InnerClassAttributeOffset.innerClassNextOffset == 0 || 556 length % InnerClassAttributeOffset.innerClassNextOffset == EnclosingMethodAttributeOffset.enclosingMethodAttributeSize, 557 "just checking"); 558 } 559 for (int i = 0; i < length; i += InnerClassAttributeOffset.innerClassNextOffset) { 560 if (i == length - EnclosingMethodAttributeOffset.enclosingMethodAttributeSize) { 561 break; 562 } 563 int ioff = innerClassList.at(i + 564 InnerClassAttributeOffset.innerClassInnerClassInfoOffset); 565 // 'ioff' can be zero. 566 // refer to JVM spec. section 4.7.5. 567 if (ioff != 0) { 568 Symbol innerName = getConstants().getKlassNameAt(ioff); 569 Symbol myname = getName(); 570 int ooff = innerClassList.at(i + 571 InnerClassAttributeOffset.innerClassOuterClassInfoOffset); 572 // for anonymous classes inner_name_index of InnerClasses 573 // attribute is zero. 574 int innerNameIndex = innerClassList.at(i + 575 InnerClassAttributeOffset.innerClassInnerNameOffset); 576 // if this is not a member (anonymous, local etc.), 'ooff' will be zero 577 // refer to JVM spec. section 4.7.5. 578 if (ooff == 0) { 579 if (includeLocals) { 580 // does it looks like my local class? 581 if (innerName.equals(sym) && 582 innerName.asString().startsWith(myname.asString())) { 583 // exclude anonymous classes. 584 return (innerNameIndex != 0); 585 } 586 } 587 } else { 588 Symbol outerName = getConstants().getKlassNameAt(ooff); 589 590 // include only if current class is outer class. 591 if (outerName.equals(myname) && innerName.equals(sym)) { 592 return true; 593 } 594 } 595 } 596 } // for inner classes 597 return false; 598 } else { 599 return false; 600 } 601 } 602 implementsInterface(Klass k)603 public boolean implementsInterface(Klass k) { 604 if (Assert.ASSERTS_ENABLED) { 605 Assert.that(k.isInterface(), "should not reach here"); 606 } 607 KlassArray interfaces = getTransitiveInterfaces(); 608 final int len = interfaces.length(); 609 for (int i = 0; i < len; i++) { 610 if (interfaces.getAt(i).equals(k)) return true; 611 } 612 return false; 613 } 614 computeSubtypeOf(Klass k)615 boolean computeSubtypeOf(Klass k) { 616 if (k.isInterface()) { 617 return implementsInterface(k); 618 } else { 619 return super.computeSubtypeOf(k); 620 } 621 } 622 printValueOn(PrintStream tty)623 public void printValueOn(PrintStream tty) { 624 tty.print("InstanceKlass for " + getName().asString()); 625 } 626 iterateFields(MetadataVisitor visitor)627 public void iterateFields(MetadataVisitor visitor) { 628 super.iterateFields(visitor); 629 visitor.doMetadata(arrayKlasses, true); 630 // visitor.doOop(methods, true); 631 // visitor.doOop(localInterfaces, true); 632 // visitor.doOop(transitiveInterfaces, true); 633 visitor.doCInt(nonstaticFieldSize, true); 634 visitor.doCInt(staticFieldSize, true); 635 visitor.doCInt(staticOopFieldCount, true); 636 visitor.doCInt(nonstaticOopMapSize, true); 637 visitor.doCInt(isMarkedDependent, true); 638 visitor.doCInt(initState, true); 639 visitor.doCInt(itableLen, true); 640 } 641 642 /* 643 * Visit the static fields of this InstanceKlass with the obj of 644 * the visitor set to the oop holding the fields, which is 645 * currently the java mirror. 646 */ iterateStaticFields(OopVisitor visitor)647 public void iterateStaticFields(OopVisitor visitor) { 648 visitor.setObj(getJavaMirror()); 649 visitor.prologue(); 650 iterateStaticFieldsInternal(visitor); 651 visitor.epilogue(); 652 653 } 654 iterateStaticFieldsInternal(OopVisitor visitor)655 void iterateStaticFieldsInternal(OopVisitor visitor) { 656 int length = getJavaFieldsCount(); 657 for (int index = 0; index < length; index++) { 658 short accessFlags = getFieldAccessFlags(index); 659 FieldType type = new FieldType(getFieldSignature(index)); 660 AccessFlags access = new AccessFlags(accessFlags); 661 if (access.isStatic()) { 662 visitField(visitor, type, index); 663 } 664 } 665 } 666 getJavaSuper()667 public Klass getJavaSuper() { 668 return getSuper(); 669 } 670 671 public static class StaticField { 672 public AccessFlags flags; 673 public Field field; 674 StaticField(Field field, AccessFlags flags)675 StaticField(Field field, AccessFlags flags) { 676 this.field = field; 677 this.flags = flags; 678 } 679 } 680 getStaticFields()681 public Field[] getStaticFields() { 682 U2Array fields = getFields(); 683 int length = getJavaFieldsCount(); 684 ArrayList<Field> result = new ArrayList<>(); 685 for (int index = 0; index < length; index++) { 686 Field f = newField(index); 687 if (f.isStatic()) { 688 result.add(f); 689 } 690 } 691 return result.toArray(new Field[result.size()]); 692 } 693 iterateNonStaticFields(OopVisitor visitor, Oop obj)694 public void iterateNonStaticFields(OopVisitor visitor, Oop obj) { 695 if (getSuper() != null) { 696 ((InstanceKlass) getSuper()).iterateNonStaticFields(visitor, obj); 697 } 698 int length = getJavaFieldsCount(); 699 for (int index = 0; index < length; index++) { 700 short accessFlags = getFieldAccessFlags(index); 701 FieldType type = new FieldType(getFieldSignature(index)); 702 AccessFlags access = new AccessFlags(accessFlags); 703 if (!access.isStatic()) { 704 visitField(visitor, type, index); 705 } 706 } 707 } 708 709 /** Field access by name. */ findLocalField(String name, String sig)710 public Field findLocalField(String name, String sig) { 711 int length = getJavaFieldsCount(); 712 for (int i = 0; i < length; i++) { 713 Symbol f_name = getFieldName(i); 714 Symbol f_sig = getFieldSignature(i); 715 if (f_name.equals(name) && f_sig.equals(sig)) { 716 return newField(i); 717 } 718 } 719 720 return null; 721 } 722 723 /** Find field in direct superinterfaces. */ findInterfaceField(String name, String sig)724 public Field findInterfaceField(String name, String sig) { 725 KlassArray interfaces = getLocalInterfaces(); 726 int n = interfaces.length(); 727 for (int i = 0; i < n; i++) { 728 InstanceKlass intf1 = (InstanceKlass) interfaces.getAt(i); 729 if (Assert.ASSERTS_ENABLED) { 730 Assert.that(intf1.isInterface(), "just checking type"); 731 } 732 // search for field in current interface 733 Field f = intf1.findLocalField(name, sig); 734 if (f != null) { 735 if (Assert.ASSERTS_ENABLED) { 736 Assert.that(f.getAccessFlagsObj().isStatic(), "interface field must be static"); 737 } 738 return f; 739 } 740 // search for field in direct superinterfaces 741 f = intf1.findInterfaceField(name, sig); 742 if (f != null) return f; 743 } 744 // otherwise field lookup fails 745 return null; 746 } 747 748 /** Find field according to JVM spec 5.4.3.2, returns the klass in 749 which the field is defined. */ findField(String name, String sig)750 public Field findField(String name, String sig) { 751 // search order according to newest JVM spec (5.4.3.2, p.167). 752 // 1) search for field in current klass 753 Field f = findLocalField(name, sig); 754 if (f != null) return f; 755 756 // 2) search for field recursively in direct superinterfaces 757 f = findInterfaceField(name, sig); 758 if (f != null) return f; 759 760 // 3) apply field lookup recursively if superclass exists 761 InstanceKlass supr = (InstanceKlass) getSuper(); 762 if (supr != null) return supr.findField(name, sig); 763 764 // 4) otherwise field lookup fails 765 return null; 766 } 767 768 /** Find field according to JVM spec 5.4.3.2, returns the klass in 769 which the field is defined (retained only for backward 770 compatibility with jdbx) */ findFieldDbg(String name, String sig)771 public Field findFieldDbg(String name, String sig) { 772 return findField(name, sig); 773 } 774 775 /** Get field by its index in the fields array. Only designed for 776 use in a debugging system. */ getFieldByIndex(int fieldIndex)777 public Field getFieldByIndex(int fieldIndex) { 778 return newField(fieldIndex); 779 } 780 781 782 /** Return a List of SA Fields for the fields declared in this class. 783 Inherited fields are not included. 784 Return an empty list if there are no fields declared in this class. 785 Only designed for use in a debugging system. */ getImmediateFields()786 public List<Field> getImmediateFields() { 787 // A list of Fields for each field declared in this class/interface, 788 // not including inherited fields. 789 int length = getJavaFieldsCount(); 790 List<Field> immediateFields = new ArrayList<>(length); 791 for (int index = 0; index < length; index++) { 792 immediateFields.add(getFieldByIndex(index)); 793 } 794 795 return immediateFields; 796 } 797 798 /** Return a List of SA Fields for all the java fields in this class, 799 including all inherited fields. This includes hidden 800 fields. Thus the returned list can contain fields with 801 the same name. 802 Return an empty list if there are no fields. 803 Only designed for use in a debugging system. */ getAllFields()804 public List<Field> getAllFields() { 805 // Contains a Field for each field in this class, including immediate 806 // fields and inherited fields. 807 List<Field> allFields = getImmediateFields(); 808 809 // transitiveInterfaces contains all interfaces implemented 810 // by this class and its superclass chain with no duplicates. 811 812 KlassArray interfaces = getTransitiveInterfaces(); 813 int n = interfaces.length(); 814 for (int i = 0; i < n; i++) { 815 InstanceKlass intf1 = (InstanceKlass) interfaces.getAt(i); 816 if (Assert.ASSERTS_ENABLED) { 817 Assert.that(intf1.isInterface(), "just checking type"); 818 } 819 allFields.addAll(intf1.getImmediateFields()); 820 } 821 822 // Get all fields in the superclass, recursively. But, don't 823 // include fields in interfaces implemented by superclasses; 824 // we already have all those. 825 if (!isInterface()) { 826 InstanceKlass supr; 827 if ( (supr = (InstanceKlass) getSuper()) != null) { 828 allFields.addAll(supr.getImmediateFields()); 829 } 830 } 831 832 return allFields; 833 } 834 835 836 /** Return a List of SA Methods declared directly in this class/interface. 837 Return an empty list if there are none, or if this isn't a class/ 838 interface. 839 */ getImmediateMethods()840 public List<Method> getImmediateMethods() { 841 // Contains a Method for each method declared in this class/interface 842 // not including inherited methods. 843 844 MethodArray methods = getMethods(); 845 int length = methods.length(); 846 Method[] tmp = new Method[length]; 847 848 IntArray methodOrdering = getMethodOrdering(); 849 if (methodOrdering.length() != length) { 850 // no ordering info present 851 for (int index = 0; index < length; index++) { 852 tmp[index] = methods.at(index); 853 } 854 } else { 855 for (int index = 0; index < length; index++) { 856 int originalIndex = methodOrdering.at(index); 857 tmp[originalIndex] = methods.at(index); 858 } 859 } 860 861 return Arrays.asList(tmp); 862 } 863 864 /** Return a List containing an SA InstanceKlass for each 865 interface named in this class's 'implements' clause. 866 */ getDirectImplementedInterfaces()867 public List<Klass> getDirectImplementedInterfaces() { 868 // Contains an InstanceKlass for each interface in this classes 869 // 'implements' clause. 870 871 KlassArray interfaces = getLocalInterfaces(); 872 int length = interfaces.length(); 873 List<Klass> directImplementedInterfaces = new ArrayList<>(length); 874 875 for (int index = 0; index < length; index ++) { 876 directImplementedInterfaces.add(interfaces.getAt(index)); 877 } 878 879 return directImplementedInterfaces; 880 } 881 arrayKlassImpl(boolean orNull, int n)882 public Klass arrayKlassImpl(boolean orNull, int n) { 883 // FIXME: in reflective system this would need to change to 884 // actually allocate 885 if (getArrayKlasses() == null) { return null; } 886 ObjArrayKlass oak = (ObjArrayKlass) getArrayKlasses(); 887 if (orNull) { 888 return oak.arrayKlassOrNull(n); 889 } 890 return oak.arrayKlass(n); 891 } 892 arrayKlassImpl(boolean orNull)893 public Klass arrayKlassImpl(boolean orNull) { 894 return arrayKlassImpl(orNull, 1); 895 } 896 signature()897 public String signature() { 898 return "L" + super.signature() + ";"; 899 } 900 901 /** Find method in vtable. */ findMethod(String name, String sig)902 public Method findMethod(String name, String sig) { 903 return findMethod(getMethods(), name, sig); 904 } 905 906 /** Breakpoint support (see methods on Method* for details) */ getBreakpoints()907 public BreakpointInfo getBreakpoints() { 908 if (!VM.getVM().isJvmtiSupported()) { 909 return null; 910 } 911 Address addr = getAddress().getAddressAt(breakpoints.getOffset()); 912 return (BreakpointInfo) VMObjectFactory.newObject(BreakpointInfo.class, addr); 913 } 914 getMethodOrdering()915 public IntArray getMethodOrdering() { 916 Address addr = getAddress().getAddressAt(methodOrdering.getOffset()); 917 return (IntArray) VMObjectFactory.newObject(IntArray.class, addr); 918 } 919 getFields()920 public U2Array getFields() { 921 Address addr = getAddress().getAddressAt(fields.getOffset()); 922 return (U2Array) VMObjectFactory.newObject(U2Array.class, addr); 923 } 924 getInnerClasses()925 public U2Array getInnerClasses() { 926 Address addr = getAddress().getAddressAt(innerClasses.getOffset()); 927 return (U2Array) VMObjectFactory.newObject(U2Array.class, addr); 928 } 929 930 931 //---------------------------------------------------------------------- 932 // Internals only below this point 933 // 934 visitField(OopVisitor visitor, FieldType type, int index)935 private void visitField(OopVisitor visitor, FieldType type, int index) { 936 Field f = newField(index); 937 if (type.isOop()) { 938 visitor.doOop((OopField) f, false); 939 return; 940 } 941 if (type.isByte()) { 942 visitor.doByte((ByteField) f, false); 943 return; 944 } 945 if (type.isChar()) { 946 visitor.doChar((CharField) f, false); 947 return; 948 } 949 if (type.isDouble()) { 950 visitor.doDouble((DoubleField) f, false); 951 return; 952 } 953 if (type.isFloat()) { 954 visitor.doFloat((FloatField) f, false); 955 return; 956 } 957 if (type.isInt()) { 958 visitor.doInt((IntField) f, false); 959 return; 960 } 961 if (type.isLong()) { 962 visitor.doLong((LongField) f, false); 963 return; 964 } 965 if (type.isShort()) { 966 visitor.doShort((ShortField) f, false); 967 return; 968 } 969 if (type.isBoolean()) { 970 visitor.doBoolean((BooleanField) f, false); 971 return; 972 } 973 } 974 975 // Creates new field from index in fields TypeArray newField(int index)976 private Field newField(int index) { 977 FieldType type = new FieldType(getFieldSignature(index)); 978 if (type.isOop()) { 979 if (VM.getVM().isCompressedOopsEnabled()) { 980 return new NarrowOopField(this, index); 981 } else { 982 return new OopField(this, index); 983 } 984 } 985 if (type.isByte()) { 986 return new ByteField(this, index); 987 } 988 if (type.isChar()) { 989 return new CharField(this, index); 990 } 991 if (type.isDouble()) { 992 return new DoubleField(this, index); 993 } 994 if (type.isFloat()) { 995 return new FloatField(this, index); 996 } 997 if (type.isInt()) { 998 return new IntField(this, index); 999 } 1000 if (type.isLong()) { 1001 return new LongField(this, index); 1002 } 1003 if (type.isShort()) { 1004 return new ShortField(this, index); 1005 } 1006 if (type.isBoolean()) { 1007 return new BooleanField(this, index); 1008 } 1009 throw new RuntimeException("Illegal field type at index " + index); 1010 } 1011 findMethod(MethodArray methods, String name, String signature)1012 private static Method findMethod(MethodArray methods, String name, String signature) { 1013 int index = linearSearch(methods, name, signature); 1014 if (index != -1) { 1015 return methods.at(index); 1016 } else { 1017 return null; 1018 } 1019 } 1020 linearSearch(MethodArray methods, String name, String signature)1021 private static int linearSearch(MethodArray methods, String name, String signature) { 1022 int len = (int) methods.length(); 1023 for (int index = 0; index < len; index++) { 1024 Method m = methods.at(index); 1025 if (m.getSignature().equals(signature) && m.getName().equals(name)) { 1026 return index; 1027 } 1028 } 1029 return -1; 1030 } 1031 dumpReplayData(PrintStream out)1032 public void dumpReplayData(PrintStream out) { 1033 ConstantPool cp = getConstants(); 1034 1035 // Try to record related loaded classes 1036 Klass sub = getSubklassKlass(); 1037 while (sub != null) { 1038 if (sub instanceof InstanceKlass) { 1039 out.println("instanceKlass " + sub.getName().asString()); 1040 } 1041 sub = sub.getNextSiblingKlass(); 1042 } 1043 1044 final int length = (int) cp.getLength(); 1045 out.print("ciInstanceKlass " + getName().asString() + " " + (isLinked() ? 1 : 0) + " " + (isInitialized() ? 1 : 0) + " " + length); 1046 for (int index = 1; index < length; index++) { 1047 out.print(" " + cp.getTags().at(index)); 1048 } 1049 out.println(); 1050 if (isInitialized()) { 1051 Field[] staticFields = getStaticFields(); 1052 for (int i = 0; i < staticFields.length; i++) { 1053 Field f = staticFields[i]; 1054 Oop mirror = getJavaMirror(); 1055 if (f.isFinal() && !f.hasInitialValue()) { 1056 out.print("staticfield " + getName().asString() + " " + 1057 OopUtilities.escapeString(f.getID().getName()) + " " + 1058 f.getFieldType().getSignature().asString() + " "); 1059 if (f instanceof ByteField) { 1060 ByteField bf = (ByteField)f; 1061 out.println(bf.getValue(mirror)); 1062 } else if (f instanceof BooleanField) { 1063 BooleanField bf = (BooleanField)f; 1064 out.println(bf.getValue(mirror) ? 1 : 0); 1065 } else if (f instanceof ShortField) { 1066 ShortField bf = (ShortField)f; 1067 out.println(bf.getValue(mirror)); 1068 } else if (f instanceof CharField) { 1069 CharField bf = (CharField)f; 1070 out.println(bf.getValue(mirror) & 0xffff); 1071 } else if (f instanceof IntField) { 1072 IntField bf = (IntField)f; 1073 out.println(bf.getValue(mirror)); 1074 } else if (f instanceof LongField) { 1075 LongField bf = (LongField)f; 1076 out.println(bf.getValue(mirror)); 1077 } else if (f instanceof FloatField) { 1078 FloatField bf = (FloatField)f; 1079 out.println(Float.floatToRawIntBits(bf.getValue(mirror))); 1080 } else if (f instanceof DoubleField) { 1081 DoubleField bf = (DoubleField)f; 1082 out.println(Double.doubleToRawLongBits(bf.getValue(mirror))); 1083 } else if (f instanceof OopField) { 1084 OopField bf = (OopField)f; 1085 1086 Oop value = bf.getValue(mirror); 1087 if (value == null) { 1088 out.println("null"); 1089 } else if (value.isInstance()) { 1090 Instance inst = (Instance)value; 1091 if (inst.isA(SystemDictionary.getStringKlass())) { 1092 out.println("\"" + OopUtilities.stringOopToEscapedString(inst) + "\""); 1093 } else { 1094 out.println(inst.getKlass().getName().asString()); 1095 } 1096 } else if (value.isObjArray()) { 1097 ObjArray oa = (ObjArray)value; 1098 Klass ek = (ObjArrayKlass)oa.getKlass(); 1099 out.println(oa.getLength() + " " + ek.getName().asString()); 1100 } else if (value.isTypeArray()) { 1101 TypeArray ta = (TypeArray)value; 1102 out.println(ta.getLength()); 1103 } else { 1104 out.println(value); 1105 } 1106 } 1107 } 1108 } 1109 } 1110 } 1111 } 1112