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