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