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