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