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 public static interface InnerClassAttributeOffset { 478 // from JVM spec. "InnerClasses" attribute 479 public static final int innerClassInnerClassInfoOffset = 0; 480 public static final int innerClassOuterClassInfoOffset = 1; 481 public static final int innerClassInnerNameOffset = 2; 482 public static final int innerClassAccessFlagsOffset = 3; 483 public static final int innerClassNextOffset = 4; 484 }; 485 486 public static interface EnclosingMethodAttributeOffset { 487 public static final int enclosing_method_class_index_offset = 0; 488 public static final int enclosing_method_method_index_offset = 1; 489 public static final int enclosing_method_attribute_size = 2; 490 }; 491 492 // refer to compute_modifier_flags in VM code. 493 public long computeModifierFlags() { 494 long access = getAccessFlags(); 495 // But check if it happens to be member class. 496 U2Array innerClassList = getInnerClasses(); 497 int length = (innerClassList == null)? 0 : (int) innerClassList.length(); 498 if (length > 0) { 499 if (Assert.ASSERTS_ENABLED) { 500 Assert.that(length % InnerClassAttributeOffset.innerClassNextOffset == 0 || 501 length % InnerClassAttributeOffset.innerClassNextOffset == EnclosingMethodAttributeOffset.enclosing_method_attribute_size, 502 "just checking"); 503 } 504 for (int i = 0; i < length; i += InnerClassAttributeOffset.innerClassNextOffset) { 505 if (i == length - EnclosingMethodAttributeOffset.enclosing_method_attribute_size) { 506 break; 507 } 508 int ioff = innerClassList.at(i + 509 InnerClassAttributeOffset.innerClassInnerClassInfoOffset); 510 // 'ioff' can be zero. 511 // refer to JVM spec. section 4.7.5. 512 if (ioff != 0) { 513 // only look at classes that are already loaded 514 // since we are looking for the flags for our self. 515 Symbol name = getConstants().getKlassNameAt(ioff); 516 517 if (name.equals(getName())) { 518 // This is really a member class 519 access = innerClassList.at(i + 520 InnerClassAttributeOffset.innerClassAccessFlagsOffset); 521 break; 522 } 523 } 524 } // for inner classes 525 } 526 527 // Remember to strip ACC_SUPER bit 528 return (access & (~JVM_ACC_SUPER)) & JVM_ACC_WRITTEN_FLAGS; 529 } 530 531 532 // whether given Symbol is name of an inner/nested Klass of this Klass? 533 // anonymous and local classes are excluded. 534 public boolean isInnerClassName(Symbol sym) { 535 return isInInnerClasses(sym, false); 536 } 537 538 // whether given Symbol is name of an inner/nested Klass of this Klass? 539 // anonymous classes excluded, but local classes are included. 540 public boolean isInnerOrLocalClassName(Symbol sym) { 541 return isInInnerClasses(sym, true); 542 } 543 544 private boolean isInInnerClasses(Symbol sym, boolean includeLocals) { 545 U2Array innerClassList = getInnerClasses(); 546 int length = ( innerClassList == null)? 0 : (int) innerClassList.length(); 547 if (length > 0) { 548 if (Assert.ASSERTS_ENABLED) { 549 Assert.that(length % InnerClassAttributeOffset.innerClassNextOffset == 0 || 550 length % InnerClassAttributeOffset.innerClassNextOffset == EnclosingMethodAttributeOffset.enclosing_method_attribute_size, 551 "just checking"); 552 } 553 for (int i = 0; i < length; i += InnerClassAttributeOffset.innerClassNextOffset) { 554 if (i == length - EnclosingMethodAttributeOffset.enclosing_method_attribute_size) { 555 break; 556 } 557 int ioff = innerClassList.at(i + 558 InnerClassAttributeOffset.innerClassInnerClassInfoOffset); 559 // 'ioff' can be zero. 560 // refer to JVM spec. section 4.7.5. 561 if (ioff != 0) { 562 Symbol innerName = getConstants().getKlassNameAt(ioff); 563 Symbol myname = getName(); 564 int ooff = innerClassList.at(i + 565 InnerClassAttributeOffset.innerClassOuterClassInfoOffset); 566 // for anonymous classes inner_name_index of InnerClasses 567 // attribute is zero. 568 int innerNameIndex = innerClassList.at(i + 569 InnerClassAttributeOffset.innerClassInnerNameOffset); 570 // if this is not a member (anonymous, local etc.), 'ooff' will be zero 571 // refer to JVM spec. section 4.7.5. 572 if (ooff == 0) { 573 if (includeLocals) { 574 // does it looks like my local class? 575 if (innerName.equals(sym) && 576 innerName.asString().startsWith(myname.asString())) { 577 // exclude anonymous classes. 578 return (innerNameIndex != 0); 579 } 580 } 581 } else { 582 Symbol outerName = getConstants().getKlassNameAt(ooff); 583 584 // include only if current class is outer class. 585 if (outerName.equals(myname) && innerName.equals(sym)) { 586 return true; 587 } 588 } 589 } 590 } // for inner classes 591 return false; 592 } else { 593 return false; 594 } 595 } 596 597 public boolean implementsInterface(Klass k) { 598 if (Assert.ASSERTS_ENABLED) { 599 Assert.that(k.isInterface(), "should not reach here"); 600 } 601 KlassArray interfaces = getTransitiveInterfaces(); 602 final int len = interfaces.length(); 603 for (int i = 0; i < len; i++) { 604 if (interfaces.getAt(i).equals(k)) return true; 605 } 606 return false; 607 } 608 609 boolean computeSubtypeOf(Klass k) { 610 if (k.isInterface()) { 611 return implementsInterface(k); 612 } else { 613 return super.computeSubtypeOf(k); 614 } 615 } 616 617 public void printValueOn(PrintStream tty) { 618 tty.print("InstanceKlass for " + getName().asString()); 619 } 620 621 public void iterateFields(MetadataVisitor visitor) { 622 super.iterateFields(visitor); 623 visitor.doMetadata(arrayKlasses, true); 624 // visitor.doOop(methods, true); 625 // visitor.doOop(localInterfaces, true); 626 // visitor.doOop(transitiveInterfaces, true); 627 visitor.doCInt(nonstaticFieldSize, true); 628 visitor.doCInt(staticFieldSize, true); 629 visitor.doCInt(staticOopFieldCount, true); 630 visitor.doCInt(nonstaticOopMapSize, true); 631 visitor.doCInt(isMarkedDependent, true); 632 visitor.doCInt(initState, true); 633 visitor.doCInt(itableLen, true); 634 } 635 636 /* 637 * Visit the static fields of this InstanceKlass with the obj of 638 * the visitor set to the oop holding the fields, which is 639 * currently the java mirror. 640 */ 641 public void iterateStaticFields(OopVisitor visitor) { 642 visitor.setObj(getJavaMirror()); 643 visitor.prologue(); 644 iterateStaticFieldsInternal(visitor); 645 visitor.epilogue(); 646 647 } 648 649 void iterateStaticFieldsInternal(OopVisitor visitor) { 650 int length = getJavaFieldsCount(); 651 for (int index = 0; index < length; index++) { 652 short accessFlags = getFieldAccessFlags(index); 653 FieldType type = new FieldType(getFieldSignature(index)); 654 AccessFlags access = new AccessFlags(accessFlags); 655 if (access.isStatic()) { 656 visitField(visitor, type, index); 657 } 658 } 659 } 660 661 public Klass getJavaSuper() { 662 return getSuper(); 663 } 664 665 public static class StaticField { 666 public AccessFlags flags; 667 public Field field; 668 669 StaticField(Field field, AccessFlags flags) { 670 this.field = field; 671 this.flags = flags; 672 } 673 } 674 675 public Field[] getStaticFields() { 676 U2Array fields = getFields(); 677 int length = getJavaFieldsCount(); 678 ArrayList result = new ArrayList(); 679 for (int index = 0; index < length; index++) { 680 Field f = newField(index); 681 if (f.isStatic()) { 682 result.add(f); 683 } 684 } 685 return (Field[])result.toArray(new Field[result.size()]); 686 } 687 688 public void iterateNonStaticFields(OopVisitor visitor, Oop obj) { 689 if (getSuper() != null) { 690 ((InstanceKlass) getSuper()).iterateNonStaticFields(visitor, obj); 691 } 692 int length = getJavaFieldsCount(); 693 for (int index = 0; index < length; index++) { 694 short accessFlags = getFieldAccessFlags(index); 695 FieldType type = new FieldType(getFieldSignature(index)); 696 AccessFlags access = new AccessFlags(accessFlags); 697 if (!access.isStatic()) { 698 visitField(visitor, type, index); 699 } 700 } 701 } 702 703 /** Field access by name. */ 704 public Field findLocalField(Symbol name, Symbol sig) { 705 int length = getJavaFieldsCount(); 706 for (int i = 0; i < length; i++) { 707 Symbol f_name = getFieldName(i); 708 Symbol f_sig = getFieldSignature(i); 709 if (name.equals(f_name) && sig.equals(f_sig)) { 710 return newField(i); 711 } 712 } 713 714 return null; 715 } 716 717 /** Find field in direct superinterfaces. */ 718 public Field findInterfaceField(Symbol name, Symbol sig) { 719 KlassArray interfaces = getLocalInterfaces(); 720 int n = interfaces.length(); 721 for (int i = 0; i < n; i++) { 722 InstanceKlass intf1 = (InstanceKlass) interfaces.getAt(i); 723 if (Assert.ASSERTS_ENABLED) { 724 Assert.that(intf1.isInterface(), "just checking type"); 725 } 726 // search for field in current interface 727 Field f = intf1.findLocalField(name, sig); 728 if (f != null) { 729 if (Assert.ASSERTS_ENABLED) { 730 Assert.that(f.getAccessFlagsObj().isStatic(), "interface field must be static"); 731 } 732 return f; 733 } 734 // search for field in direct superinterfaces 735 f = intf1.findInterfaceField(name, sig); 736 if (f != null) return f; 737 } 738 // otherwise field lookup fails 739 return null; 740 } 741 742 /** Find field according to JVM spec 5.4.3.2, returns the klass in 743 which the field is defined. */ 744 public Field findField(Symbol name, Symbol sig) { 745 // search order according to newest JVM spec (5.4.3.2, p.167). 746 // 1) search for field in current klass 747 Field f = findLocalField(name, sig); 748 if (f != null) return f; 749 750 // 2) search for field recursively in direct superinterfaces 751 f = findInterfaceField(name, sig); 752 if (f != null) return f; 753 754 // 3) apply field lookup recursively if superclass exists 755 InstanceKlass supr = (InstanceKlass) getSuper(); 756 if (supr != null) return supr.findField(name, sig); 757 758 // 4) otherwise field lookup fails 759 return null; 760 } 761 762 /** Find field according to JVM spec 5.4.3.2, returns the klass in 763 which the field is defined (convenience routine) */ 764 public Field findField(String name, String sig) { 765 SymbolTable symbols = VM.getVM().getSymbolTable(); 766 Symbol nameSym = symbols.probe(name); 767 Symbol sigSym = symbols.probe(sig); 768 if (nameSym == null || sigSym == null) { 769 return null; 770 } 771 return findField(nameSym, sigSym); 772 } 773 774 /** Find field according to JVM spec 5.4.3.2, returns the klass in 775 which the field is defined (retained only for backward 776 compatibility with jdbx) */ 777 public Field findFieldDbg(String name, String sig) { 778 return findField(name, sig); 779 } 780 781 /** Get field by its index in the fields array. Only designed for 782 use in a debugging system. */ 783 public Field getFieldByIndex(int fieldIndex) { 784 return newField(fieldIndex); 785 } 786 787 788 /** Return a List of SA Fields for the fields declared in this class. 789 Inherited fields are not included. 790 Return an empty list if there are no fields declared in this class. 791 Only designed for use in a debugging system. */ 792 public List getImmediateFields() { 793 // A list of Fields for each field declared in this class/interface, 794 // not including inherited fields. 795 int length = getJavaFieldsCount(); 796 List immediateFields = new ArrayList(length); 797 for (int index = 0; index < length; index++) { 798 immediateFields.add(getFieldByIndex(index)); 799 } 800 801 return immediateFields; 802 } 803 804 /** Return a List of SA Fields for all the java fields in this class, 805 including all inherited fields. This includes hidden 806 fields. Thus the returned list can contain fields with 807 the same name. 808 Return an empty list if there are no fields. 809 Only designed for use in a debugging system. */ 810 public List getAllFields() { 811 // Contains a Field for each field in this class, including immediate 812 // fields and inherited fields. 813 List allFields = getImmediateFields(); 814 815 // transitiveInterfaces contains all interfaces implemented 816 // by this class and its superclass chain with no duplicates. 817 818 KlassArray interfaces = getTransitiveInterfaces(); 819 int n = interfaces.length(); 820 for (int i = 0; i < n; i++) { 821 InstanceKlass intf1 = (InstanceKlass) interfaces.getAt(i); 822 if (Assert.ASSERTS_ENABLED) { 823 Assert.that(intf1.isInterface(), "just checking type"); 824 } 825 allFields.addAll(intf1.getImmediateFields()); 826 } 827 828 // Get all fields in the superclass, recursively. But, don't 829 // include fields in interfaces implemented by superclasses; 830 // we already have all those. 831 if (!isInterface()) { 832 InstanceKlass supr; 833 if ( (supr = (InstanceKlass) getSuper()) != null) { 834 allFields.addAll(supr.getImmediateFields()); 835 } 836 } 837 838 return allFields; 839 } 840 841 842 /** Return a List of SA Methods declared directly in this class/interface. 843 Return an empty list if there are none, or if this isn't a class/ 844 interface. 845 */ 846 public List getImmediateMethods() { 847 // Contains a Method for each method declared in this class/interface 848 // not including inherited methods. 849 850 MethodArray methods = getMethods(); 851 int length = methods.length(); 852 Object[] tmp = new Object[length]; 853 854 IntArray methodOrdering = getMethodOrdering(); 855 if (methodOrdering.length() != length) { 856 // no ordering info present 857 for (int index = 0; index < length; index++) { 858 tmp[index] = methods.at(index); 859 } 860 } else { 861 for (int index = 0; index < length; index++) { 862 int originalIndex = methodOrdering.at(index); 863 tmp[originalIndex] = methods.at(index); 864 } 865 } 866 867 return Arrays.asList(tmp); 868 } 869 870 /** Return a List containing an SA InstanceKlass for each 871 interface named in this class's 'implements' clause. 872 */ 873 public List getDirectImplementedInterfaces() { 874 // Contains an InstanceKlass for each interface in this classes 875 // 'implements' clause. 876 877 KlassArray interfaces = getLocalInterfaces(); 878 int length = interfaces.length(); 879 List directImplementedInterfaces = new ArrayList(length); 880 881 for (int index = 0; index < length; index ++) { 882 directImplementedInterfaces.add(interfaces.getAt(index)); 883 } 884 885 return directImplementedInterfaces; 886 } 887 888 public Klass arrayKlassImpl(boolean orNull, int n) { 889 // FIXME: in reflective system this would need to change to 890 // actually allocate 891 if (getArrayKlasses() == null) { return null; } 892 ObjArrayKlass oak = (ObjArrayKlass) getArrayKlasses(); 893 if (orNull) { 894 return oak.arrayKlassOrNull(n); 895 } 896 return oak.arrayKlass(n); 897 } 898 899 public Klass arrayKlassImpl(boolean orNull) { 900 return arrayKlassImpl(orNull, 1); 901 } 902 903 public String signature() { 904 return "L" + super.signature() + ";"; 905 } 906 907 /** Convenience routine taking Strings; lookup is done in 908 SymbolTable. */ 909 public Method findMethod(String name, String sig) { 910 SymbolTable syms = VM.getVM().getSymbolTable(); 911 Symbol nameSym = syms.probe(name); 912 Symbol sigSym = syms.probe(sig); 913 if (nameSym == null || sigSym == null) { 914 return null; 915 } 916 return findMethod(nameSym, sigSym); 917 } 918 919 /** Find method in vtable. */ 920 public Method findMethod(Symbol name, Symbol sig) { 921 return findMethod(getMethods(), name, sig); 922 } 923 924 /** Breakpoint support (see methods on Method* for details) */ 925 public BreakpointInfo getBreakpoints() { 926 if (!VM.getVM().isJvmtiSupported()) { 927 return null; 928 } 929 Address addr = getAddress().getAddressAt(breakpoints.getOffset()); 930 return (BreakpointInfo) VMObjectFactory.newObject(BreakpointInfo.class, addr); 931 } 932 933 public IntArray getMethodOrdering() { 934 Address addr = getAddress().getAddressAt(methodOrdering.getOffset()); 935 return (IntArray) VMObjectFactory.newObject(IntArray.class, addr); 936 } 937 938 public U2Array getFields() { 939 Address addr = getAddress().getAddressAt(fields.getOffset()); 940 return (U2Array) VMObjectFactory.newObject(U2Array.class, addr); 941 } 942 943 public U2Array getInnerClasses() { 944 Address addr = getAddress().getAddressAt(innerClasses.getOffset()); 945 return (U2Array) VMObjectFactory.newObject(U2Array.class, addr); 946 } 947 948 949 //---------------------------------------------------------------------- 950 // Internals only below this point 951 // 952 953 private void visitField(OopVisitor visitor, FieldType type, int index) { 954 Field f = newField(index); 955 if (type.isOop()) { 956 visitor.doOop((OopField) f, false); 957 return; 958 } 959 if (type.isByte()) { 960 visitor.doByte((ByteField) f, false); 961 return; 962 } 963 if (type.isChar()) { 964 visitor.doChar((CharField) f, false); 965 return; 966 } 967 if (type.isDouble()) { 968 visitor.doDouble((DoubleField) f, false); 969 return; 970 } 971 if (type.isFloat()) { 972 visitor.doFloat((FloatField) f, false); 973 return; 974 } 975 if (type.isInt()) { 976 visitor.doInt((IntField) f, false); 977 return; 978 } 979 if (type.isLong()) { 980 visitor.doLong((LongField) f, false); 981 return; 982 } 983 if (type.isShort()) { 984 visitor.doShort((ShortField) f, false); 985 return; 986 } 987 if (type.isBoolean()) { 988 visitor.doBoolean((BooleanField) f, false); 989 return; 990 } 991 } 992 993 // Creates new field from index in fields TypeArray 994 private Field newField(int index) { 995 FieldType type = new FieldType(getFieldSignature(index)); 996 if (type.isOop()) { 997 if (VM.getVM().isCompressedOopsEnabled()) { 998 return new NarrowOopField(this, index); 999 } else { 1000 return new OopField(this, index); 1001 } 1002 } 1003 if (type.isByte()) { 1004 return new ByteField(this, index); 1005 } 1006 if (type.isChar()) { 1007 return new CharField(this, index); 1008 } 1009 if (type.isDouble()) { 1010 return new DoubleField(this, index); 1011 } 1012 if (type.isFloat()) { 1013 return new FloatField(this, index); 1014 } 1015 if (type.isInt()) { 1016 return new IntField(this, index); 1017 } 1018 if (type.isLong()) { 1019 return new LongField(this, index); 1020 } 1021 if (type.isShort()) { 1022 return new ShortField(this, index); 1023 } 1024 if (type.isBoolean()) { 1025 return new BooleanField(this, index); 1026 } 1027 throw new RuntimeException("Illegal field type at index " + index); 1028 } 1029 1030 private static Method findMethod(MethodArray methods, Symbol name, Symbol signature) { 1031 int len = methods.length(); 1032 // methods are sorted, so do binary search 1033 int l = 0; 1034 int h = len - 1; 1035 while (l <= h) { 1036 int mid = (l + h) >> 1; 1037 Method m = methods.at(mid); 1038 long res = m.getName().fastCompare(name); 1039 if (res == 0) { 1040 // found matching name; do linear search to find matching signature 1041 // first, quick check for common case 1042 if (m.getSignature().equals(signature)) return m; 1043 // search downwards through overloaded methods 1044 int i; 1045 for (i = mid - 1; i >= l; i--) { 1046 Method m1 = methods.at(i); 1047 if (!m1.getName().equals(name)) break; 1048 if (m1.getSignature().equals(signature)) return m1; 1049 } 1050 // search upwards 1051 for (i = mid + 1; i <= h; i++) { 1052 Method m1 = methods.at(i); 1053 if (!m1.getName().equals(name)) break; 1054 if (m1.getSignature().equals(signature)) return m1; 1055 } 1056 // not found 1057 if (Assert.ASSERTS_ENABLED) { 1058 int index = linearSearch(methods, name, signature); 1059 if (index != -1) { 1060 throw new DebuggerException("binary search bug: should have found entry " + index); 1061 } 1062 } 1063 return null; 1064 } else if (res < 0) { 1065 l = mid + 1; 1066 } else { 1067 h = mid - 1; 1068 } 1069 } 1070 if (Assert.ASSERTS_ENABLED) { 1071 int index = linearSearch(methods, name, signature); 1072 if (index != -1) { 1073 throw new DebuggerException("binary search bug: should have found entry " + index); 1074 } 1075 } 1076 return null; 1077 } 1078 1079 private static int linearSearch(MethodArray methods, Symbol name, Symbol signature) { 1080 int len = (int) methods.length(); 1081 for (int index = 0; index < len; index++) { 1082 Method m = methods.at(index); 1083 if (m.getSignature().equals(signature) && m.getName().equals(name)) { 1084 return index; 1085 } 1086 } 1087 return -1; 1088 } 1089 1090 public void dumpReplayData(PrintStream out) { 1091 ConstantPool cp = getConstants(); 1092 1093 // Try to record related loaded classes 1094 Klass sub = getSubklassKlass(); 1095 while (sub != null) { 1096 if (sub instanceof InstanceKlass) { 1097 out.println("instanceKlass " + sub.getName().asString()); 1098 } 1099 sub = sub.getNextSiblingKlass(); 1100 } 1101 1102 final int length = (int) cp.getLength(); 1103 out.print("ciInstanceKlass " + getName().asString() + " " + (isLinked() ? 1 : 0) + " " + (isInitialized() ? 1 : 0) + " " + length); 1104 for (int index = 1; index < length; index++) { 1105 out.print(" " + cp.getTags().at(index)); 1106 } 1107 out.println(); 1108 if (isInitialized()) { 1109 Field[] staticFields = getStaticFields(); 1110 for (int i = 0; i < staticFields.length; i++) { 1111 Field f = staticFields[i]; 1112 Oop mirror = getJavaMirror(); 1113 if (f.isFinal() && !f.hasInitialValue()) { 1114 out.print("staticfield " + getName().asString() + " " + 1115 OopUtilities.escapeString(f.getID().getName()) + " " + 1116 f.getFieldType().getSignature().asString() + " "); 1117 if (f instanceof ByteField) { 1118 ByteField bf = (ByteField)f; 1119 out.println(bf.getValue(mirror)); 1120 } else if (f instanceof BooleanField) { 1121 BooleanField bf = (BooleanField)f; 1122 out.println(bf.getValue(mirror) ? 1 : 0); 1123 } else if (f instanceof ShortField) { 1124 ShortField bf = (ShortField)f; 1125 out.println(bf.getValue(mirror)); 1126 } else if (f instanceof CharField) { 1127 CharField bf = (CharField)f; 1128 out.println(bf.getValue(mirror) & 0xffff); 1129 } else if (f instanceof IntField) { 1130 IntField bf = (IntField)f; 1131 out.println(bf.getValue(mirror)); 1132 } else if (f instanceof LongField) { 1133 LongField bf = (LongField)f; 1134 out.println(bf.getValue(mirror)); 1135 } else if (f instanceof FloatField) { 1136 FloatField bf = (FloatField)f; 1137 out.println(Float.floatToRawIntBits(bf.getValue(mirror))); 1138 } else if (f instanceof DoubleField) { 1139 DoubleField bf = (DoubleField)f; 1140 out.println(Double.doubleToRawLongBits(bf.getValue(mirror))); 1141 } else if (f instanceof OopField) { 1142 OopField bf = (OopField)f; 1143 1144 Oop value = bf.getValue(mirror); 1145 if (value == null) { 1146 out.println("null"); 1147 } else if (value.isInstance()) { 1148 Instance inst = (Instance)value; 1149 if (inst.isA(SystemDictionary.getStringKlass())) { 1150 out.println("\"" + OopUtilities.stringOopToEscapedString(inst) + "\""); 1151 } else { 1152 out.println(inst.getKlass().getName().asString()); 1153 } 1154 } else if (value.isObjArray()) { 1155 ObjArray oa = (ObjArray)value; 1156 Klass ek = (ObjArrayKlass)oa.getKlass(); 1157 out.println(oa.getLength() + " " + ek.getName().asString()); 1158 } else if (value.isTypeArray()) { 1159 TypeArray ta = (TypeArray)value; 1160 out.println(ta.getLength()); 1161 } else { 1162 out.println(value); 1163 } 1164 } 1165 } 1166 } 1167 } 1168 } 1169 }