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