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