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