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