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