1 /* 2 * Copyright (c) 2000, 2017, 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 { 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_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 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_ANONYMOUS = db.lookupIntConstant("InstanceKlass::_misc_is_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 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 193 private ClassState(String value) { 194 this.value = value; 195 } 196 197 public String toString() { 198 return value; 199 } 200 201 private String value; 202 } 203 204 public int getInitStateAsInt() { return (int) initState.getValue(this); } 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 225 public boolean isLoaded() { 226 return getInitStateAsInt() >= CLASS_STATE_LOADED; 227 } 228 229 public boolean isLinked() { 230 return getInitStateAsInt() >= CLASS_STATE_LINKED; 231 } 232 233 public boolean isInitialized() { 234 return getInitStateAsInt() == CLASS_STATE_FULLY_INITIALIZED; 235 } 236 237 public boolean isNotInitialized() { 238 return getInitStateAsInt() < CLASS_STATE_BEING_INITIALIZED; 239 } 240 241 public boolean isBeingInitialized() { 242 return getInitStateAsInt() == CLASS_STATE_BEING_INITIALIZED; 243 } 244 245 public boolean isInErrorState() { 246 return getInitStateAsInt() == CLASS_STATE_INITIALIZATION_ERROR; 247 } 248 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 271 public long getObjectSize(Oop object) { 272 return getSizeHelper() * VM.getVM().getAddressSize(); 273 } 274 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 (isAnonymous()) { 285 size += wordLength; 286 } 287 if (hasStoredFingerprint()) { 288 size += 8; // uint64_t 289 } 290 return alignSize(size); 291 } 292 293 private int getMiscFlags() { 294 return (int) miscFlags.getValue(this); 295 } 296 297 public boolean isAnonymous() { 298 return (getMiscFlags() & MISC_IS_ANONYMOUS) != 0; 299 } 300 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 312 public boolean hasStoredFingerprint() { 313 return shouldStoreFingerprint() || isShared(); 314 } 315 316 public boolean isShared() { 317 VM vm = VM.getVM(); 318 if (vm.isSharingEnabled()) { 319 // This is not the same implementation as the C++ function MetaspaceObj::is_shared() 320 // bool MetaspaceObj::is_shared() const { 321 // return MetaspaceShared::is_in_shared_space(this); 322 // } 323 // However, MetaspaceShared::is_in_shared_space is complicated and hard to emulate in 324 // Java code, so let's do this by looking up from the shared dictionary. Of course, 325 // this works for shared InstanceKlass only and does not work for other types of 326 // MetaspaceObj in the CDS shared archive. 327 Dictionary sharedDictionary = vm.getSystemDictionary().sharedDictionary(); 328 if (sharedDictionary != null) { 329 if (sharedDictionary.contains(this)) { 330 return true; 331 } 332 } 333 } 334 return false; 335 } 336 337 public static long getHeaderSize() { return headerSize; } 338 339 public short getFieldAccessFlags(int index) { 340 return getFields().at(index * FIELD_SLOTS + ACCESS_FLAGS_OFFSET); 341 } 342 343 public short getFieldNameIndex(int index) { 344 if (index >= getJavaFieldsCount()) throw new IndexOutOfBoundsException("not a Java field;"); 345 return getFields().at(index * FIELD_SLOTS + NAME_INDEX_OFFSET); 346 } 347 348 public Symbol getFieldName(int index) { 349 int nameIndex = getFields().at(index * FIELD_SLOTS + NAME_INDEX_OFFSET); 350 if (index < getJavaFieldsCount()) { 351 return getConstants().getSymbolAt(nameIndex); 352 } else { 353 return vmSymbols.symbolAt(nameIndex); 354 } 355 } 356 357 public short getFieldSignatureIndex(int index) { 358 if (index >= getJavaFieldsCount()) throw new IndexOutOfBoundsException("not a Java field;"); 359 return getFields().at(index * FIELD_SLOTS + SIGNATURE_INDEX_OFFSET); 360 } 361 362 public Symbol getFieldSignature(int index) { 363 int signatureIndex = getFields().at(index * FIELD_SLOTS + SIGNATURE_INDEX_OFFSET); 364 if (index < getJavaFieldsCount()) { 365 return getConstants().getSymbolAt(signatureIndex); 366 } else { 367 return vmSymbols.symbolAt(signatureIndex); 368 } 369 } 370 371 public short getFieldGenericSignatureIndex(int index) { 372 // int len = getFields().length(); 373 int allFieldsCount = getAllFieldsCount(); 374 int generic_signature_slot = allFieldsCount * FIELD_SLOTS; 375 for (int i = 0; i < allFieldsCount; i++) { 376 short flags = getFieldAccessFlags(i); 377 AccessFlags access = new AccessFlags(flags); 378 if (i == index) { 379 if (access.fieldHasGenericSignature()) { 380 return getFields().at(generic_signature_slot); 381 } else { 382 return 0; 383 } 384 } else { 385 if (access.fieldHasGenericSignature()) { 386 generic_signature_slot ++; 387 } 388 } 389 } 390 return 0; 391 } 392 393 public Symbol getFieldGenericSignature(int index) { 394 short genericSignatureIndex = getFieldGenericSignatureIndex(index); 395 if (genericSignatureIndex != 0) { 396 return getConstants().getSymbolAt(genericSignatureIndex); 397 } 398 return null; 399 } 400 401 public short getFieldInitialValueIndex(int index) { 402 if (index >= getJavaFieldsCount()) throw new IndexOutOfBoundsException("not a Java field;"); 403 return getFields().at(index * FIELD_SLOTS + INITVAL_INDEX_OFFSET); 404 } 405 406 public int getFieldOffset(int index) { 407 U2Array fields = getFields(); 408 short lo = fields.at(index * FIELD_SLOTS + LOW_OFFSET); 409 short hi = fields.at(index * FIELD_SLOTS + HIGH_OFFSET); 410 if ((lo & FIELDINFO_TAG_MASK) == FIELDINFO_TAG_OFFSET) { 411 return VM.getVM().buildIntFromShorts(lo, hi) >> FIELDINFO_TAG_SIZE; 412 } 413 throw new RuntimeException("should not reach here"); 414 } 415 416 // Accessors for declared fields 417 public Klass getArrayKlasses() { return (Klass) arrayKlasses.getValue(this); } 418 public MethodArray getMethods() { return new MethodArray(methods.getValue(getAddress())); } 419 420 public MethodArray getDefaultMethods() { 421 if (defaultMethods != null) { 422 Address addr = defaultMethods.getValue(getAddress()); 423 if ((addr != null) && (addr.getAddressAt(0) != null)) { 424 return new MethodArray(addr); 425 } else { 426 return null; 427 } 428 } else { 429 return null; 430 } 431 } 432 433 public KlassArray getLocalInterfaces() { return new KlassArray(localInterfaces.getValue(getAddress())); } 434 public KlassArray getTransitiveInterfaces() { return new KlassArray(transitiveInterfaces.getValue(getAddress())); } 435 public int getJavaFieldsCount() { return (int) javaFieldsCount.getValue(this); } 436 public int getAllFieldsCount() { 437 int len = getFields().length(); 438 int allFieldsCount = 0; 439 for (; allFieldsCount*FIELD_SLOTS < len; allFieldsCount++) { 440 short flags = getFieldAccessFlags(allFieldsCount); 441 AccessFlags access = new AccessFlags(flags); 442 if (access.fieldHasGenericSignature()) { 443 len --; 444 } 445 } 446 return allFieldsCount; 447 } 448 public ConstantPool getConstants() { return (ConstantPool) constants.getValue(this); } 449 public Symbol getSourceFileName() { return getConstants().getSymbolAt(sourceFileNameIndex.getValue(this)); } 450 public String getSourceDebugExtension(){ return CStringUtilities.getString(sourceDebugExtension.getValue(getAddress())); } 451 public long getNonstaticFieldSize() { return nonstaticFieldSize.getValue(this); } 452 public long getStaticOopFieldCount() { return staticOopFieldCount.getValue(this); } 453 public long getNonstaticOopMapSize() { return nonstaticOopMapSize.getValue(this); } 454 public boolean getIsMarkedDependent() { return isMarkedDependent.getValue(this) != 0; } 455 public long getItableLen() { return itableLen.getValue(this); } 456 public long majorVersion() { return majorVersion.getValue(this); } 457 public long minorVersion() { return minorVersion.getValue(this); } 458 public Symbol getGenericSignature() { 459 long index = genericSignatureIndex.getValue(this); 460 if (index != 0) { 461 return getConstants().getSymbolAt(index); 462 } else { 463 return null; 464 } 465 } 466 467 // "size helper" == instance size in words 468 public long getSizeHelper() { 469 int lh = getLayoutHelper(); 470 if (Assert.ASSERTS_ENABLED) { 471 Assert.that(lh > 0, "layout helper initialized for instance class"); 472 } 473 return lh / VM.getVM().getAddressSize(); 474 } 475 476 // same as enum InnerClassAttributeOffset in VM code. 477 private static class InnerClassAttributeOffset { 478 // from JVM spec. "InnerClasses" attribute 479 public static int innerClassInnerClassInfoOffset; 480 public static int innerClassOuterClassInfoOffset; 481 public static int innerClassInnerNameOffset; 482 public static int innerClassAccessFlagsOffset; 483 public static int innerClassNextOffset; 484 static { 485 VM.registerVMInitializedObserver(new Observer() { 486 public void update(Observable o, Object data) { 487 initialize(VM.getVM().getTypeDataBase()); 488 } 489 }); 490 } 491 492 private static synchronized void initialize(TypeDataBase db) { 493 innerClassInnerClassInfoOffset = db.lookupIntConstant( 494 "InstanceKlass::inner_class_inner_class_info_offset").intValue(); 495 innerClassOuterClassInfoOffset = db.lookupIntConstant( 496 "InstanceKlass::inner_class_outer_class_info_offset").intValue(); 497 innerClassInnerNameOffset = db.lookupIntConstant( 498 "InstanceKlass::inner_class_inner_name_offset").intValue(); 499 innerClassAccessFlagsOffset = db.lookupIntConstant( 500 "InstanceKlass::inner_class_access_flags_offset").intValue(); 501 innerClassNextOffset = db.lookupIntConstant( 502 "InstanceKlass::inner_class_next_offset").intValue(); 503 } 504 } 505 506 private static class EnclosingMethodAttributeOffset { 507 public static int enclosingMethodAttributeSize; 508 static { 509 VM.registerVMInitializedObserver(new Observer() { 510 public void update(Observable o, Object data) { 511 initialize(VM.getVM().getTypeDataBase()); 512 } 513 }); 514 } 515 private static synchronized void initialize(TypeDataBase db) { 516 enclosingMethodAttributeSize = db.lookupIntConstant("InstanceKlass::enclosing_method_attribute_size").intValue(); 517 } 518 } 519 520 // refer to compute_modifier_flags in VM code. 521 public long computeModifierFlags() { 522 long access = getAccessFlags(); 523 // But check if it happens to be member class. 524 U2Array innerClassList = getInnerClasses(); 525 int length = (innerClassList == null)? 0 : (int) innerClassList.length(); 526 if (length > 0) { 527 if (Assert.ASSERTS_ENABLED) { 528 Assert.that(length % InnerClassAttributeOffset.innerClassNextOffset == 0 || 529 length % InnerClassAttributeOffset.innerClassNextOffset == EnclosingMethodAttributeOffset.enclosingMethodAttributeSize, 530 "just checking"); 531 } 532 for (int i = 0; i < length; i += InnerClassAttributeOffset.innerClassNextOffset) { 533 if (i == length - EnclosingMethodAttributeOffset.enclosingMethodAttributeSize) { 534 break; 535 } 536 int ioff = innerClassList.at(i + 537 InnerClassAttributeOffset.innerClassInnerClassInfoOffset); 538 // 'ioff' can be zero. 539 // refer to JVM spec. section 4.7.5. 540 if (ioff != 0) { 541 // only look at classes that are already loaded 542 // since we are looking for the flags for our self. 543 Symbol name = getConstants().getKlassNameAt(ioff); 544 545 if (name.equals(getName())) { 546 // This is really a member class 547 access = innerClassList.at(i + 548 InnerClassAttributeOffset.innerClassAccessFlagsOffset); 549 break; 550 } 551 } 552 } // for inner classes 553 } 554 555 // Remember to strip ACC_SUPER bit 556 return (access & (~JVM_ACC_SUPER)) & JVM_ACC_WRITTEN_FLAGS; 557 } 558 559 560 // whether given Symbol is name of an inner/nested Klass of this Klass? 561 // anonymous and local classes are excluded. 562 public boolean isInnerClassName(Symbol sym) { 563 return isInInnerClasses(sym, false); 564 } 565 566 // whether given Symbol is name of an inner/nested Klass of this Klass? 567 // anonymous classes excluded, but local classes are included. 568 public boolean isInnerOrLocalClassName(Symbol sym) { 569 return isInInnerClasses(sym, true); 570 } 571 572 private boolean isInInnerClasses(Symbol sym, boolean includeLocals) { 573 U2Array innerClassList = getInnerClasses(); 574 int length = ( innerClassList == null)? 0 : (int) innerClassList.length(); 575 if (length > 0) { 576 if (Assert.ASSERTS_ENABLED) { 577 Assert.that(length % InnerClassAttributeOffset.innerClassNextOffset == 0 || 578 length % InnerClassAttributeOffset.innerClassNextOffset == EnclosingMethodAttributeOffset.enclosingMethodAttributeSize, 579 "just checking"); 580 } 581 for (int i = 0; i < length; i += InnerClassAttributeOffset.innerClassNextOffset) { 582 if (i == length - EnclosingMethodAttributeOffset.enclosingMethodAttributeSize) { 583 break; 584 } 585 int ioff = innerClassList.at(i + 586 InnerClassAttributeOffset.innerClassInnerClassInfoOffset); 587 // 'ioff' can be zero. 588 // refer to JVM spec. section 4.7.5. 589 if (ioff != 0) { 590 Symbol innerName = getConstants().getKlassNameAt(ioff); 591 Symbol myname = getName(); 592 int ooff = innerClassList.at(i + 593 InnerClassAttributeOffset.innerClassOuterClassInfoOffset); 594 // for anonymous classes inner_name_index of InnerClasses 595 // attribute is zero. 596 int innerNameIndex = innerClassList.at(i + 597 InnerClassAttributeOffset.innerClassInnerNameOffset); 598 // if this is not a member (anonymous, local etc.), 'ooff' will be zero 599 // refer to JVM spec. section 4.7.5. 600 if (ooff == 0) { 601 if (includeLocals) { 602 // does it looks like my local class? 603 if (innerName.equals(sym) && 604 innerName.asString().startsWith(myname.asString())) { 605 // exclude anonymous classes. 606 return (innerNameIndex != 0); 607 } 608 } 609 } else { 610 Symbol outerName = getConstants().getKlassNameAt(ooff); 611 612 // include only if current class is outer class. 613 if (outerName.equals(myname) && innerName.equals(sym)) { 614 return true; 615 } 616 } 617 } 618 } // for inner classes 619 return false; 620 } else { 621 return false; 622 } 623 } 624 625 public boolean implementsInterface(Klass k) { 626 if (Assert.ASSERTS_ENABLED) { 627 Assert.that(k.isInterface(), "should not reach here"); 628 } 629 KlassArray interfaces = getTransitiveInterfaces(); 630 final int len = interfaces.length(); 631 for (int i = 0; i < len; i++) { 632 if (interfaces.getAt(i).equals(k)) return true; 633 } 634 return false; 635 } 636 637 boolean computeSubtypeOf(Klass k) { 638 if (k.isInterface()) { 639 return implementsInterface(k); 640 } else { 641 return super.computeSubtypeOf(k); 642 } 643 } 644 645 public void printValueOn(PrintStream tty) { 646 tty.print("InstanceKlass for " + getName().asString()); 647 } 648 649 public void iterateFields(MetadataVisitor visitor) { 650 super.iterateFields(visitor); 651 visitor.doMetadata(arrayKlasses, true); 652 // visitor.doOop(methods, true); 653 // visitor.doOop(localInterfaces, true); 654 // visitor.doOop(transitiveInterfaces, true); 655 visitor.doCInt(nonstaticFieldSize, true); 656 visitor.doCInt(staticFieldSize, true); 657 visitor.doCInt(staticOopFieldCount, true); 658 visitor.doCInt(nonstaticOopMapSize, true); 659 visitor.doCInt(isMarkedDependent, true); 660 visitor.doCInt(initState, true); 661 visitor.doCInt(itableLen, true); 662 } 663 664 /* 665 * Visit the static fields of this InstanceKlass with the obj of 666 * the visitor set to the oop holding the fields, which is 667 * currently the java mirror. 668 */ 669 public void iterateStaticFields(OopVisitor visitor) { 670 visitor.setObj(getJavaMirror()); 671 visitor.prologue(); 672 iterateStaticFieldsInternal(visitor); 673 visitor.epilogue(); 674 675 } 676 677 void iterateStaticFieldsInternal(OopVisitor visitor) { 678 int length = getJavaFieldsCount(); 679 for (int index = 0; index < length; index++) { 680 short accessFlags = getFieldAccessFlags(index); 681 FieldType type = new FieldType(getFieldSignature(index)); 682 AccessFlags access = new AccessFlags(accessFlags); 683 if (access.isStatic()) { 684 visitField(visitor, type, index); 685 } 686 } 687 } 688 689 public Klass getJavaSuper() { 690 return getSuper(); 691 } 692 693 public static class StaticField { 694 public AccessFlags flags; 695 public Field field; 696 697 StaticField(Field field, AccessFlags flags) { 698 this.field = field; 699 this.flags = flags; 700 } 701 } 702 703 public Field[] getStaticFields() { 704 U2Array fields = getFields(); 705 int length = getJavaFieldsCount(); 706 ArrayList result = new ArrayList(); 707 for (int index = 0; index < length; index++) { 708 Field f = newField(index); 709 if (f.isStatic()) { 710 result.add(f); 711 } 712 } 713 return (Field[])result.toArray(new Field[result.size()]); 714 } 715 716 public void iterateNonStaticFields(OopVisitor visitor, Oop obj) { 717 if (getSuper() != null) { 718 ((InstanceKlass) getSuper()).iterateNonStaticFields(visitor, obj); 719 } 720 int length = getJavaFieldsCount(); 721 for (int index = 0; index < length; index++) { 722 short accessFlags = getFieldAccessFlags(index); 723 FieldType type = new FieldType(getFieldSignature(index)); 724 AccessFlags access = new AccessFlags(accessFlags); 725 if (!access.isStatic()) { 726 visitField(visitor, type, index); 727 } 728 } 729 } 730 731 /** Field access by name. */ 732 public Field findLocalField(String name, String sig) { 733 int length = getJavaFieldsCount(); 734 for (int i = 0; i < length; i++) { 735 Symbol f_name = getFieldName(i); 736 Symbol f_sig = getFieldSignature(i); 737 if (f_name.equals(name) && f_sig.equals(sig)) { 738 return newField(i); 739 } 740 } 741 742 return null; 743 } 744 745 /** Find field in direct superinterfaces. */ 746 public Field findInterfaceField(String name, String sig) { 747 KlassArray interfaces = getLocalInterfaces(); 748 int n = interfaces.length(); 749 for (int i = 0; i < n; i++) { 750 InstanceKlass intf1 = (InstanceKlass) interfaces.getAt(i); 751 if (Assert.ASSERTS_ENABLED) { 752 Assert.that(intf1.isInterface(), "just checking type"); 753 } 754 // search for field in current interface 755 Field f = intf1.findLocalField(name, sig); 756 if (f != null) { 757 if (Assert.ASSERTS_ENABLED) { 758 Assert.that(f.getAccessFlagsObj().isStatic(), "interface field must be static"); 759 } 760 return f; 761 } 762 // search for field in direct superinterfaces 763 f = intf1.findInterfaceField(name, sig); 764 if (f != null) return f; 765 } 766 // otherwise field lookup fails 767 return null; 768 } 769 770 /** Find field according to JVM spec 5.4.3.2, returns the klass in 771 which the field is defined. */ 772 public Field findField(String name, String sig) { 773 // search order according to newest JVM spec (5.4.3.2, p.167). 774 // 1) search for field in current klass 775 Field f = findLocalField(name, sig); 776 if (f != null) return f; 777 778 // 2) search for field recursively in direct superinterfaces 779 f = findInterfaceField(name, sig); 780 if (f != null) return f; 781 782 // 3) apply field lookup recursively if superclass exists 783 InstanceKlass supr = (InstanceKlass) getSuper(); 784 if (supr != null) return supr.findField(name, sig); 785 786 // 4) otherwise field lookup fails 787 return null; 788 } 789 790 /** Find field according to JVM spec 5.4.3.2, returns the klass in 791 which the field is defined (retained only for backward 792 compatibility with jdbx) */ 793 public Field findFieldDbg(String name, String sig) { 794 return findField(name, sig); 795 } 796 797 /** Get field by its index in the fields array. Only designed for 798 use in a debugging system. */ 799 public Field getFieldByIndex(int fieldIndex) { 800 return newField(fieldIndex); 801 } 802 803 804 /** Return a List of SA Fields for the fields declared in this class. 805 Inherited fields are not included. 806 Return an empty list if there are no fields declared in this class. 807 Only designed for use in a debugging system. */ 808 public List getImmediateFields() { 809 // A list of Fields for each field declared in this class/interface, 810 // not including inherited fields. 811 int length = getJavaFieldsCount(); 812 List immediateFields = new ArrayList(length); 813 for (int index = 0; index < length; index++) { 814 immediateFields.add(getFieldByIndex(index)); 815 } 816 817 return immediateFields; 818 } 819 820 /** Return a List of SA Fields for all the java fields in this class, 821 including all inherited fields. This includes hidden 822 fields. Thus the returned list can contain fields with 823 the same name. 824 Return an empty list if there are no fields. 825 Only designed for use in a debugging system. */ 826 public List getAllFields() { 827 // Contains a Field for each field in this class, including immediate 828 // fields and inherited fields. 829 List allFields = getImmediateFields(); 830 831 // transitiveInterfaces contains all interfaces implemented 832 // by this class and its superclass chain with no duplicates. 833 834 KlassArray interfaces = getTransitiveInterfaces(); 835 int n = interfaces.length(); 836 for (int i = 0; i < n; i++) { 837 InstanceKlass intf1 = (InstanceKlass) interfaces.getAt(i); 838 if (Assert.ASSERTS_ENABLED) { 839 Assert.that(intf1.isInterface(), "just checking type"); 840 } 841 allFields.addAll(intf1.getImmediateFields()); 842 } 843 844 // Get all fields in the superclass, recursively. But, don't 845 // include fields in interfaces implemented by superclasses; 846 // we already have all those. 847 if (!isInterface()) { 848 InstanceKlass supr; 849 if ( (supr = (InstanceKlass) getSuper()) != null) { 850 allFields.addAll(supr.getImmediateFields()); 851 } 852 } 853 854 return allFields; 855 } 856 857 858 /** Return a List of SA Methods declared directly in this class/interface. 859 Return an empty list if there are none, or if this isn't a class/ 860 interface. 861 */ 862 public List getImmediateMethods() { 863 // Contains a Method for each method declared in this class/interface 864 // not including inherited methods. 865 866 MethodArray methods = getMethods(); 867 int length = methods.length(); 868 Object[] tmp = new Object[length]; 869 870 IntArray methodOrdering = getMethodOrdering(); 871 if (methodOrdering.length() != length) { 872 // no ordering info present 873 for (int index = 0; index < length; index++) { 874 tmp[index] = methods.at(index); 875 } 876 } else { 877 for (int index = 0; index < length; index++) { 878 int originalIndex = methodOrdering.at(index); 879 tmp[originalIndex] = methods.at(index); 880 } 881 } 882 883 return Arrays.asList(tmp); 884 } 885 886 /** Return a List containing an SA InstanceKlass for each 887 interface named in this class's 'implements' clause. 888 */ 889 public List getDirectImplementedInterfaces() { 890 // Contains an InstanceKlass for each interface in this classes 891 // 'implements' clause. 892 893 KlassArray interfaces = getLocalInterfaces(); 894 int length = interfaces.length(); 895 List directImplementedInterfaces = new ArrayList(length); 896 897 for (int index = 0; index < length; index ++) { 898 directImplementedInterfaces.add(interfaces.getAt(index)); 899 } 900 901 return directImplementedInterfaces; 902 } 903 904 public Klass arrayKlassImpl(boolean orNull, int n) { 905 // FIXME: in reflective system this would need to change to 906 // actually allocate 907 if (getArrayKlasses() == null) { return null; } 908 ObjArrayKlass oak = (ObjArrayKlass) getArrayKlasses(); 909 if (orNull) { 910 return oak.arrayKlassOrNull(n); 911 } 912 return oak.arrayKlass(n); 913 } 914 915 public Klass arrayKlassImpl(boolean orNull) { 916 return arrayKlassImpl(orNull, 1); 917 } 918 919 public String signature() { 920 return "L" + super.signature() + ";"; 921 } 922 923 /** Find method in vtable. */ 924 public Method findMethod(String name, String sig) { 925 return findMethod(getMethods(), name, sig); 926 } 927 928 /** Breakpoint support (see methods on Method* for details) */ 929 public BreakpointInfo getBreakpoints() { 930 if (!VM.getVM().isJvmtiSupported()) { 931 return null; 932 } 933 Address addr = getAddress().getAddressAt(breakpoints.getOffset()); 934 return (BreakpointInfo) VMObjectFactory.newObject(BreakpointInfo.class, addr); 935 } 936 937 public IntArray getMethodOrdering() { 938 Address addr = getAddress().getAddressAt(methodOrdering.getOffset()); 939 return (IntArray) VMObjectFactory.newObject(IntArray.class, addr); 940 } 941 942 public U2Array getFields() { 943 Address addr = getAddress().getAddressAt(fields.getOffset()); 944 return (U2Array) VMObjectFactory.newObject(U2Array.class, addr); 945 } 946 947 public U2Array getInnerClasses() { 948 Address addr = getAddress().getAddressAt(innerClasses.getOffset()); 949 return (U2Array) VMObjectFactory.newObject(U2Array.class, addr); 950 } 951 952 953 //---------------------------------------------------------------------- 954 // Internals only below this point 955 // 956 957 private void visitField(OopVisitor visitor, FieldType type, int index) { 958 Field f = newField(index); 959 if (type.isOop()) { 960 visitor.doOop((OopField) f, false); 961 return; 962 } 963 if (type.isByte()) { 964 visitor.doByte((ByteField) f, false); 965 return; 966 } 967 if (type.isChar()) { 968 visitor.doChar((CharField) f, false); 969 return; 970 } 971 if (type.isDouble()) { 972 visitor.doDouble((DoubleField) f, false); 973 return; 974 } 975 if (type.isFloat()) { 976 visitor.doFloat((FloatField) f, false); 977 return; 978 } 979 if (type.isInt()) { 980 visitor.doInt((IntField) f, false); 981 return; 982 } 983 if (type.isLong()) { 984 visitor.doLong((LongField) f, false); 985 return; 986 } 987 if (type.isShort()) { 988 visitor.doShort((ShortField) f, false); 989 return; 990 } 991 if (type.isBoolean()) { 992 visitor.doBoolean((BooleanField) f, false); 993 return; 994 } 995 } 996 997 // Creates new field from index in fields TypeArray 998 private Field newField(int index) { 999 FieldType type = new FieldType(getFieldSignature(index)); 1000 if (type.isOop()) { 1001 if (VM.getVM().isCompressedOopsEnabled()) { 1002 return new NarrowOopField(this, index); 1003 } else { 1004 return new OopField(this, index); 1005 } 1006 } 1007 if (type.isByte()) { 1008 return new ByteField(this, index); 1009 } 1010 if (type.isChar()) { 1011 return new CharField(this, index); 1012 } 1013 if (type.isDouble()) { 1014 return new DoubleField(this, index); 1015 } 1016 if (type.isFloat()) { 1017 return new FloatField(this, index); 1018 } 1019 if (type.isInt()) { 1020 return new IntField(this, index); 1021 } 1022 if (type.isLong()) { 1023 return new LongField(this, index); 1024 } 1025 if (type.isShort()) { 1026 return new ShortField(this, index); 1027 } 1028 if (type.isBoolean()) { 1029 return new BooleanField(this, index); 1030 } 1031 throw new RuntimeException("Illegal field type at index " + index); 1032 } 1033 1034 private static Method findMethod(MethodArray methods, String name, String signature) { 1035 int index = linearSearch(methods, name, signature); 1036 if (index != -1) { 1037 return methods.at(index); 1038 } else { 1039 return null; 1040 } 1041 } 1042 1043 private static int linearSearch(MethodArray methods, String name, String signature) { 1044 int len = (int) methods.length(); 1045 for (int index = 0; index < len; index++) { 1046 Method m = methods.at(index); 1047 if (m.getSignature().equals(signature) && m.getName().equals(name)) { 1048 return index; 1049 } 1050 } 1051 return -1; 1052 } 1053 1054 public void dumpReplayData(PrintStream out) { 1055 ConstantPool cp = getConstants(); 1056 1057 // Try to record related loaded classes 1058 Klass sub = getSubklassKlass(); 1059 while (sub != null) { 1060 if (sub instanceof InstanceKlass) { 1061 out.println("instanceKlass " + sub.getName().asString()); 1062 } 1063 sub = sub.getNextSiblingKlass(); 1064 } 1065 1066 final int length = (int) cp.getLength(); 1067 out.print("ciInstanceKlass " + getName().asString() + " " + (isLinked() ? 1 : 0) + " " + (isInitialized() ? 1 : 0) + " " + length); 1068 for (int index = 1; index < length; index++) { 1069 out.print(" " + cp.getTags().at(index)); 1070 } 1071 out.println(); 1072 if (isInitialized()) { 1073 Field[] staticFields = getStaticFields(); 1074 for (int i = 0; i < staticFields.length; i++) { 1075 Field f = staticFields[i]; 1076 Oop mirror = getJavaMirror(); 1077 if (f.isFinal() && !f.hasInitialValue()) { 1078 out.print("staticfield " + getName().asString() + " " + 1079 OopUtilities.escapeString(f.getID().getName()) + " " + 1080 f.getFieldType().getSignature().asString() + " "); 1081 if (f instanceof ByteField) { 1082 ByteField bf = (ByteField)f; 1083 out.println(bf.getValue(mirror)); 1084 } else if (f instanceof BooleanField) { 1085 BooleanField bf = (BooleanField)f; 1086 out.println(bf.getValue(mirror) ? 1 : 0); 1087 } else if (f instanceof ShortField) { 1088 ShortField bf = (ShortField)f; 1089 out.println(bf.getValue(mirror)); 1090 } else if (f instanceof CharField) { 1091 CharField bf = (CharField)f; 1092 out.println(bf.getValue(mirror) & 0xffff); 1093 } else if (f instanceof IntField) { 1094 IntField bf = (IntField)f; 1095 out.println(bf.getValue(mirror)); 1096 } else if (f instanceof LongField) { 1097 LongField bf = (LongField)f; 1098 out.println(bf.getValue(mirror)); 1099 } else if (f instanceof FloatField) { 1100 FloatField bf = (FloatField)f; 1101 out.println(Float.floatToRawIntBits(bf.getValue(mirror))); 1102 } else if (f instanceof DoubleField) { 1103 DoubleField bf = (DoubleField)f; 1104 out.println(Double.doubleToRawLongBits(bf.getValue(mirror))); 1105 } else if (f instanceof OopField) { 1106 OopField bf = (OopField)f; 1107 1108 Oop value = bf.getValue(mirror); 1109 if (value == null) { 1110 out.println("null"); 1111 } else if (value.isInstance()) { 1112 Instance inst = (Instance)value; 1113 if (inst.isA(SystemDictionary.getStringKlass())) { 1114 out.println("\"" + OopUtilities.stringOopToEscapedString(inst) + "\""); 1115 } else { 1116 out.println(inst.getKlass().getName().asString()); 1117 } 1118 } else if (value.isObjArray()) { 1119 ObjArray oa = (ObjArray)value; 1120 Klass ek = (ObjArrayKlass)oa.getKlass(); 1121 out.println(oa.getLength() + " " + ek.getName().asString()); 1122 } else if (value.isTypeArray()) { 1123 TypeArray ta = (TypeArray)value; 1124 out.println(ta.getLength()); 1125 } else { 1126 out.println(value); 1127 } 1128 } 1129 } 1130 } 1131 } 1132 } 1133 }