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