comparison agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java @ 0:a61af66fc99e jdk7-b24

Initial load
author duke
date Sat, 01 Dec 2007 00:00:00 +0000
parents
children ba764ed4b6f2
comparison
equal deleted inserted replaced
-1:000000000000 0:a61af66fc99e
1 /*
2 * Copyright 2000-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20 * CA 95054 USA or visit www.sun.com if you need additional information or
21 * have any 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 = new OopField(type.getOopField("_source_file_name"), Oop.getHeaderSize());
86 sourceDebugExtension = new OopField(type.getOopField("_source_debug_extension"), Oop.getHeaderSize());
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 staticOopFieldSize = new CIntField(type.getCIntegerField("_static_oop_field_size"), 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 = new OopField(type.getOopField("_generic_signature"), Oop.getHeaderSize());
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 OopField sourceFileName;
139 private static OopField sourceDebugExtension;
140 private static OopField innerClasses;
141 private static CIntField nonstaticFieldSize;
142 private static CIntField staticFieldSize;
143 private static CIntField staticOopFieldSize;
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 OopField 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 static long getHeaderSize() { return headerSize; }
245
246 // Accessors for declared fields
247 public Klass getArrayKlasses() { return (Klass) arrayKlasses.getValue(this); }
248 public ObjArray getMethods() { return (ObjArray) methods.getValue(this); }
249 public TypeArray getMethodOrdering() { return (TypeArray) methodOrdering.getValue(this); }
250 public ObjArray getLocalInterfaces() { return (ObjArray) localInterfaces.getValue(this); }
251 public ObjArray getTransitiveInterfaces() { return (ObjArray) transitiveInterfaces.getValue(this); }
252 public long nofImplementors() { return nofImplementors.getValue(this); }
253 public Klass getImplementor() { return (Klass) implementors[0].getValue(this); }
254 public Klass getImplementor(int i) { return (Klass) implementors[i].getValue(this); }
255 public TypeArray getFields() { return (TypeArray) fields.getValue(this); }
256 public ConstantPool getConstants() { return (ConstantPool) constants.getValue(this); }
257 public Oop getClassLoader() { return classLoader.getValue(this); }
258 public Oop getProtectionDomain() { return protectionDomain.getValue(this); }
259 public ObjArray getSigners() { return (ObjArray) signers.getValue(this); }
260 public Symbol getSourceFileName() { return (Symbol) sourceFileName.getValue(this); }
261 public Symbol getSourceDebugExtension(){ return (Symbol) sourceDebugExtension.getValue(this); }
262 public TypeArray getInnerClasses() { return (TypeArray) innerClasses.getValue(this); }
263 public long getNonstaticFieldSize() { return nonstaticFieldSize.getValue(this); }
264 public long getStaticFieldSize() { return staticFieldSize.getValue(this); }
265 public long getStaticOopFieldSize() { return staticOopFieldSize.getValue(this); }
266 public long getNonstaticOopMapSize() { return nonstaticOopMapSize.getValue(this); }
267 public boolean getIsMarkedDependent() { return isMarkedDependent.getValue(this) != 0; }
268 public long getVtableLen() { return vtableLen.getValue(this); }
269 public long getItableLen() { return itableLen.getValue(this); }
270 public Symbol getGenericSignature() { return (Symbol) genericSignature.getValue(this); }
271 public long majorVersion() { return majorVersion.getValue(this); }
272 public long minorVersion() { return minorVersion.getValue(this); }
273
274 // "size helper" == instance size in words
275 public long getSizeHelper() {
276 int lh = getLayoutHelper();
277 if (Assert.ASSERTS_ENABLED) {
278 Assert.that(lh > 0, "layout helper initialized for instance class");
279 }
280 return lh / VM.getVM().getAddressSize();
281 }
282
283 // same as enum InnerClassAttributeOffset in VM code.
284 public static interface InnerClassAttributeOffset {
285 // from JVM spec. "InnerClasses" attribute
286 public static final int innerClassInnerClassInfoOffset = 0;
287 public static final int innerClassOuterClassInfoOffset = 1;
288 public static final int innerClassInnerNameOffset = 2;
289 public static final int innerClassAccessFlagsOffset = 3;
290 public static final int innerClassNextOffset = 4;
291 };
292
293 // refer to compute_modifier_flags in VM code.
294 public long computeModifierFlags() {
295 long access = getAccessFlags();
296 // But check if it happens to be member class.
297 TypeArray innerClassList = getInnerClasses();
298 int length = ( innerClassList == null)? 0 : (int) innerClassList.getLength();
299 if (length > 0) {
300 if (Assert.ASSERTS_ENABLED) {
301 Assert.that(length % InnerClassAttributeOffset.innerClassNextOffset == 0, "just checking");
302 }
303 for (int i = 0; i < length; i += InnerClassAttributeOffset.innerClassNextOffset) {
304 int ioff = innerClassList.getShortAt(i +
305 InnerClassAttributeOffset.innerClassInnerClassInfoOffset);
306 // 'ioff' can be zero.
307 // refer to JVM spec. section 4.7.5.
308 if (ioff != 0) {
309 // only look at classes that are already loaded
310 // since we are looking for the flags for our self.
311 Oop classInfo = getConstants().getObjAt(ioff);
312 Symbol name = null;
313 if (classInfo instanceof Klass) {
314 name = ((Klass) classInfo).getName();
315 } else if (classInfo instanceof Symbol) {
316 name = (Symbol) classInfo;
317 } else {
318 throw new RuntimeException("should not reach here");
319 }
320
321 if (name.equals(getName())) {
322 // This is really a member class
323 access = innerClassList.getShortAt(i +
324 InnerClassAttributeOffset.innerClassAccessFlagsOffset);
325 break;
326 }
327 }
328 } // for inner classes
329 }
330
331 // Remember to strip ACC_SUPER bit
332 return (access & (~JVM_ACC_SUPER)) & JVM_ACC_WRITTEN_FLAGS;
333 }
334
335
336 // whether given Symbol is name of an inner/nested Klass of this Klass?
337 // anonymous and local classes are excluded.
338 public boolean isInnerClassName(Symbol sym) {
339 return isInInnerClasses(sym, false);
340 }
341
342 // whether given Symbol is name of an inner/nested Klass of this Klass?
343 // anonymous classes excluded, but local classes are included.
344 public boolean isInnerOrLocalClassName(Symbol sym) {
345 return isInInnerClasses(sym, true);
346 }
347
348 private boolean isInInnerClasses(Symbol sym, boolean includeLocals) {
349 TypeArray innerClassList = getInnerClasses();
350 int length = ( innerClassList == null)? 0 : (int) innerClassList.getLength();
351 if (length > 0) {
352 if (Assert.ASSERTS_ENABLED) {
353 Assert.that(length % InnerClassAttributeOffset.innerClassNextOffset == 0, "just checking");
354 }
355 for (int i = 0; i < length; i += InnerClassAttributeOffset.innerClassNextOffset) {
356 int ioff = innerClassList.getShortAt(i +
357 InnerClassAttributeOffset.innerClassInnerClassInfoOffset);
358 // 'ioff' can be zero.
359 // refer to JVM spec. section 4.7.5.
360 if (ioff != 0) {
361 Oop iclassInfo = getConstants().getObjAt(ioff);
362 Symbol innerName = null;
363 if (iclassInfo instanceof Klass) {
364 innerName = ((Klass) iclassInfo).getName();
365 } else if (iclassInfo instanceof Symbol) {
366 innerName = (Symbol) iclassInfo;
367 } else {
368 throw new RuntimeException("should not reach here");
369 }
370
371 Symbol myname = getName();
372 int ooff = innerClassList.getShortAt(i +
373 InnerClassAttributeOffset.innerClassOuterClassInfoOffset);
374 // for anonymous classes inner_name_index of InnerClasses
375 // attribute is zero.
376 int innerNameIndex = innerClassList.getShortAt(i +
377 InnerClassAttributeOffset.innerClassInnerNameOffset);
378 // if this is not a member (anonymous, local etc.), 'ooff' will be zero
379 // refer to JVM spec. section 4.7.5.
380 if (ooff == 0) {
381 if (includeLocals) {
382 // does it looks like my local class?
383 if (innerName.equals(sym) &&
384 innerName.asString().startsWith(myname.asString())) {
385 // exclude anonymous classes.
386 return (innerNameIndex != 0);
387 }
388 }
389 } else {
390 Oop oclassInfo = getConstants().getObjAt(ooff);
391 Symbol outerName = null;
392 if (oclassInfo instanceof Klass) {
393 outerName = ((Klass) oclassInfo).getName();
394 } else if (oclassInfo instanceof Symbol) {
395 outerName = (Symbol) oclassInfo;
396 } else {
397 throw new RuntimeException("should not reach here");
398 }
399
400 // include only if current class is outer class.
401 if (outerName.equals(myname) && innerName.equals(sym)) {
402 return true;
403 }
404 }
405 }
406 } // for inner classes
407 return false;
408 } else {
409 return false;
410 }
411 }
412
413 public boolean implementsInterface(Klass k) {
414 if (Assert.ASSERTS_ENABLED) {
415 Assert.that(k.isInterface(), "should not reach here");
416 }
417 ObjArray interfaces = getTransitiveInterfaces();
418 final int len = (int) interfaces.getLength();
419 for (int i = 0; i < len; i++) {
420 if (interfaces.getObjAt(i).equals(k)) return true;
421 }
422 return false;
423 }
424
425 boolean computeSubtypeOf(Klass k) {
426 if (k.isInterface()) {
427 return implementsInterface(k);
428 } else {
429 return super.computeSubtypeOf(k);
430 }
431 }
432
433 public void printValueOn(PrintStream tty) {
434 tty.print("InstanceKlass for " + getName().asString());
435 }
436
437 public void iterateFields(OopVisitor visitor, boolean doVMFields) {
438 super.iterateFields(visitor, doVMFields);
439 if (doVMFields) {
440 visitor.doOop(arrayKlasses, true);
441 visitor.doOop(methods, true);
442 visitor.doOop(methodOrdering, true);
443 visitor.doOop(localInterfaces, true);
444 visitor.doOop(transitiveInterfaces, true);
445 visitor.doCInt(nofImplementors, true);
446 for (int i = 0; i < IMPLEMENTORS_LIMIT; i++)
447 visitor.doOop(implementors[i], true);
448 visitor.doOop(fields, true);
449 visitor.doOop(constants, true);
450 visitor.doOop(classLoader, true);
451 visitor.doOop(protectionDomain, true);
452 visitor.doOop(signers, true);
453 visitor.doOop(sourceFileName, true);
454 visitor.doOop(innerClasses, true);
455 visitor.doCInt(nonstaticFieldSize, true);
456 visitor.doCInt(staticFieldSize, true);
457 visitor.doCInt(staticOopFieldSize, true);
458 visitor.doCInt(nonstaticOopMapSize, true);
459 visitor.doCInt(isMarkedDependent, true);
460 visitor.doCInt(initState, true);
461 visitor.doCInt(vtableLen, true);
462 visitor.doCInt(itableLen, true);
463 }
464
465 TypeArray fields = getFields();
466 int length = (int) fields.getLength();
467 for (int index = 0; index < length; index += NEXT_OFFSET) {
468 short accessFlags = fields.getShortAt(index + ACCESS_FLAGS_OFFSET);
469 short signatureIndex = fields.getShortAt(index + SIGNATURE_INDEX_OFFSET);
470
471 FieldType type = new FieldType((Symbol) getConstants().getObjAt(signatureIndex));
472 AccessFlags access = new AccessFlags(accessFlags);
473 if (access.isStatic()) {
474 visitField(visitor, type, index);
475 }
476 }
477 }
478
479 public Klass getJavaSuper() {
480 return getSuper();
481 }
482
483 public void iterateNonStaticFields(OopVisitor visitor) {
484 if (getSuper() != null) {
485 ((InstanceKlass) getSuper()).iterateNonStaticFields(visitor);
486 }
487 TypeArray fields = getFields();
488
489 int length = (int) fields.getLength();
490 for (int index = 0; index < length; index += NEXT_OFFSET) {
491 short accessFlags = fields.getShortAt(index + ACCESS_FLAGS_OFFSET);
492 short signatureIndex = fields.getShortAt(index + SIGNATURE_INDEX_OFFSET);
493
494 FieldType type = new FieldType((Symbol) getConstants().getObjAt(signatureIndex));
495 AccessFlags access = new AccessFlags(accessFlags);
496 if (!access.isStatic()) {
497 visitField(visitor, type, index);
498 }
499 }
500 }
501
502 /** Field access by name. */
503 public Field findLocalField(Symbol name, Symbol sig) {
504 TypeArray fields = getFields();
505 int n = (int) fields.getLength();
506 ConstantPool cp = getConstants();
507 for (int i = 0; i < n; i += NEXT_OFFSET) {
508 int nameIndex = fields.getShortAt(i + NAME_INDEX_OFFSET);
509 int sigIndex = fields.getShortAt(i + SIGNATURE_INDEX_OFFSET);
510 Symbol f_name = cp.getSymbolAt(nameIndex);
511 Symbol f_sig = cp.getSymbolAt(sigIndex);
512 if (name.equals(f_name) && sig.equals(f_sig)) {
513 return newField(i);
514 }
515 }
516
517 return null;
518 }
519
520 /** Find field in direct superinterfaces. */
521 public Field findInterfaceField(Symbol name, Symbol sig) {
522 ObjArray interfaces = getLocalInterfaces();
523 int n = (int) interfaces.getLength();
524 for (int i = 0; i < n; i++) {
525 InstanceKlass intf1 = (InstanceKlass) interfaces.getObjAt(i);
526 if (Assert.ASSERTS_ENABLED) {
527 Assert.that(intf1.isInterface(), "just checking type");
528 }
529 // search for field in current interface
530 Field f = intf1.findLocalField(name, sig);
531 if (f != null) {
532 if (Assert.ASSERTS_ENABLED) {
533 Assert.that(f.getAccessFlagsObj().isStatic(), "interface field must be static");
534 }
535 return f;
536 }
537 // search for field in direct superinterfaces
538 f = intf1.findInterfaceField(name, sig);
539 if (f != null) return f;
540 }
541 // otherwise field lookup fails
542 return null;
543 }
544
545 /** Find field according to JVM spec 5.4.3.2, returns the klass in
546 which the field is defined. */
547 public Field findField(Symbol name, Symbol sig) {
548 // search order according to newest JVM spec (5.4.3.2, p.167).
549 // 1) search for field in current klass
550 Field f = findLocalField(name, sig);
551 if (f != null) return f;
552
553 // 2) search for field recursively in direct superinterfaces
554 f = findInterfaceField(name, sig);
555 if (f != null) return f;
556
557 // 3) apply field lookup recursively if superclass exists
558 InstanceKlass supr = (InstanceKlass) getSuper();
559 if (supr != null) return supr.findField(name, sig);
560
561 // 4) otherwise field lookup fails
562 return null;
563 }
564
565 /** Find field according to JVM spec 5.4.3.2, returns the klass in
566 which the field is defined (convenience routine) */
567 public Field findField(String name, String sig) {
568 SymbolTable symbols = VM.getVM().getSymbolTable();
569 Symbol nameSym = symbols.probe(name);
570 Symbol sigSym = symbols.probe(sig);
571 if (nameSym == null || sigSym == null) {
572 return null;
573 }
574 return findField(nameSym, sigSym);
575 }
576
577 /** Find field according to JVM spec 5.4.3.2, returns the klass in
578 which the field is defined (retained only for backward
579 compatibility with jdbx) */
580 public Field findFieldDbg(String name, String sig) {
581 return findField(name, sig);
582 }
583
584 /** Get field by its index in the fields array. Only designed for
585 use in a debugging system. */
586 public Field getFieldByIndex(int fieldArrayIndex) {
587 return newField(fieldArrayIndex);
588 }
589
590
591 /** Return a List of SA Fields for the fields declared in this class.
592 Inherited fields are not included.
593 Return an empty list if there are no fields declared in this class.
594 Only designed for use in a debugging system. */
595 public List getImmediateFields() {
596 // A list of Fields for each field declared in this class/interface,
597 // not including inherited fields.
598 TypeArray fields = getFields();
599
600 int length = (int) fields.getLength();
601 List immediateFields = new ArrayList(length / NEXT_OFFSET);
602 for (int index = 0; index < length; index += NEXT_OFFSET) {
603 immediateFields.add(getFieldByIndex(index));
604 }
605
606 return immediateFields;
607 }
608
609 /** Return a List of SA Fields for all the java fields in this class,
610 including all inherited fields. This includes hidden
611 fields. Thus the returned list can contain fields with
612 the same name.
613 Return an empty list if there are no fields.
614 Only designed for use in a debugging system. */
615 public List getAllFields() {
616 // Contains a Field for each field in this class, including immediate
617 // fields and inherited fields.
618 List allFields = getImmediateFields();
619
620 // transitiveInterfaces contains all interfaces implemented
621 // by this class and its superclass chain with no duplicates.
622
623 ObjArray interfaces = getTransitiveInterfaces();
624 int n = (int) interfaces.getLength();
625 for (int i = 0; i < n; i++) {
626 InstanceKlass intf1 = (InstanceKlass) interfaces.getObjAt(i);
627 if (Assert.ASSERTS_ENABLED) {
628 Assert.that(intf1.isInterface(), "just checking type");
629 }
630 allFields.addAll(intf1.getImmediateFields());
631 }
632
633 // Get all fields in the superclass, recursively. But, don't
634 // include fields in interfaces implemented by superclasses;
635 // we already have all those.
636 if (!isInterface()) {
637 InstanceKlass supr;
638 if ( (supr = (InstanceKlass) getSuper()) != null) {
639 allFields.addAll(supr.getImmediateFields());
640 }
641 }
642
643 return allFields;
644 }
645
646
647 /** Return a List of SA Methods declared directly in this class/interface.
648 Return an empty list if there are none, or if this isn't a class/
649 interface.
650 */
651 public List getImmediateMethods() {
652 // Contains a Method for each method declared in this class/interface
653 // not including inherited methods.
654
655 ObjArray methods = getMethods();
656 int length = (int)methods.getLength();
657 Object[] tmp = new Object[length];
658
659 TypeArray methodOrdering = getMethodOrdering();
660 if (methodOrdering.getLength() != length) {
661 // no ordering info present
662 for (int index = 0; index < length; index++) {
663 tmp[index] = methods.getObjAt(index);
664 }
665 } else {
666 for (int index = 0; index < length; index++) {
667 int originalIndex = getMethodOrdering().getIntAt(index);
668 tmp[originalIndex] = methods.getObjAt(index);
669 }
670 }
671
672 return Arrays.asList(tmp);
673 }
674
675 /** Return a List containing an SA InstanceKlass for each
676 interface named in this class's 'implements' clause.
677 */
678 public List getDirectImplementedInterfaces() {
679 // Contains an InstanceKlass for each interface in this classes
680 // 'implements' clause.
681
682 ObjArray interfaces = getLocalInterfaces();
683 int length = (int) interfaces.getLength();
684 List directImplementedInterfaces = new ArrayList(length);
685
686 for (int index = 0; index < length; index ++) {
687 directImplementedInterfaces.add(interfaces.getObjAt(index));
688 }
689
690 return directImplementedInterfaces;
691 }
692
693
694 public long getObjectSize() {
695 long bodySize = alignObjectOffset(getVtableLen() * getHeap().getOopSize())
696 + alignObjectOffset(getItableLen() * getHeap().getOopSize())
697 + (getStaticFieldSize() + getNonstaticOopMapSize()) * getHeap().getOopSize();
698 return alignObjectSize(headerSize + bodySize);
699 }
700
701 public Klass arrayKlassImpl(boolean orNull, int n) {
702 // FIXME: in reflective system this would need to change to
703 // actually allocate
704 if (getArrayKlasses() == null) { return null; }
705 ObjArrayKlass oak = (ObjArrayKlass) getArrayKlasses();
706 if (orNull) {
707 return oak.arrayKlassOrNull(n);
708 }
709 return oak.arrayKlass(n);
710 }
711
712 public Klass arrayKlassImpl(boolean orNull) {
713 return arrayKlassImpl(orNull, 1);
714 }
715
716 public String signature() {
717 return "L" + super.signature() + ";";
718 }
719
720 /** Convenience routine taking Strings; lookup is done in
721 SymbolTable. */
722 public Method findMethod(String name, String sig) {
723 SymbolTable syms = VM.getVM().getSymbolTable();
724 Symbol nameSym = syms.probe(name);
725 Symbol sigSym = syms.probe(sig);
726 if (nameSym == null || sigSym == null) {
727 return null;
728 }
729 return findMethod(nameSym, sigSym);
730 }
731
732 /** Find method in vtable. */
733 public Method findMethod(Symbol name, Symbol sig) {
734 return findMethod(getMethods(), name, sig);
735 }
736
737 /** Breakpoint support (see methods on methodOop for details) */
738 public BreakpointInfo getBreakpoints() {
739 Address addr = getHandle().getAddressAt(Oop.getHeaderSize() + breakpoints.getOffset());
740 return (BreakpointInfo) VMObjectFactory.newObject(BreakpointInfo.class, addr);
741 }
742
743 //----------------------------------------------------------------------
744 // Internals only below this point
745 //
746
747 private void visitField(OopVisitor visitor, FieldType type, int index) {
748 Field f = newField(index);
749 if (type.isOop()) {
750 visitor.doOop((OopField) f, false);
751 return;
752 }
753 if (type.isByte()) {
754 visitor.doByte((ByteField) f, false);
755 return;
756 }
757 if (type.isChar()) {
758 visitor.doChar((CharField) f, false);
759 return;
760 }
761 if (type.isDouble()) {
762 visitor.doDouble((DoubleField) f, false);
763 return;
764 }
765 if (type.isFloat()) {
766 visitor.doFloat((FloatField) f, false);
767 return;
768 }
769 if (type.isInt()) {
770 visitor.doInt((IntField) f, false);
771 return;
772 }
773 if (type.isLong()) {
774 visitor.doLong((LongField) f, false);
775 return;
776 }
777 if (type.isShort()) {
778 visitor.doShort((ShortField) f, false);
779 return;
780 }
781 if (type.isBoolean()) {
782 visitor.doBoolean((BooleanField) f, false);
783 return;
784 }
785 }
786
787 // Creates new field from index in fields TypeArray
788 private Field newField(int index) {
789 TypeArray fields = getFields();
790 short signatureIndex = fields.getShortAt(index + SIGNATURE_INDEX_OFFSET);
791 FieldType type = new FieldType((Symbol) getConstants().getObjAt(signatureIndex));
792 if (type.isOop()) {
793 return new OopField(this, index);
794 }
795 if (type.isByte()) {
796 return new ByteField(this, index);
797 }
798 if (type.isChar()) {
799 return new CharField(this, index);
800 }
801 if (type.isDouble()) {
802 return new DoubleField(this, index);
803 }
804 if (type.isFloat()) {
805 return new FloatField(this, index);
806 }
807 if (type.isInt()) {
808 return new IntField(this, index);
809 }
810 if (type.isLong()) {
811 return new LongField(this, index);
812 }
813 if (type.isShort()) {
814 return new ShortField(this, index);
815 }
816 if (type.isBoolean()) {
817 return new BooleanField(this, index);
818 }
819 throw new RuntimeException("Illegal field type at index " + index);
820 }
821
822 private static Method findMethod(ObjArray methods, Symbol name, Symbol signature) {
823 int len = (int) methods.getLength();
824 // methods are sorted, so do binary search
825 int l = 0;
826 int h = len - 1;
827 while (l <= h) {
828 int mid = (l + h) >> 1;
829 Method m = (Method) methods.getObjAt(mid);
830 int res = m.getName().fastCompare(name);
831 if (res == 0) {
832 // found matching name; do linear search to find matching signature
833 // first, quick check for common case
834 if (m.getSignature().equals(signature)) return m;
835 // search downwards through overloaded methods
836 int i;
837 for (i = mid - 1; i >= l; i--) {
838 Method m1 = (Method) methods.getObjAt(i);
839 if (!m1.getName().equals(name)) break;
840 if (m1.getSignature().equals(signature)) return m1;
841 }
842 // search upwards
843 for (i = mid + 1; i <= h; i++) {
844 Method m1 = (Method) methods.getObjAt(i);
845 if (!m1.getName().equals(name)) break;
846 if (m1.getSignature().equals(signature)) return m1;
847 }
848 // not found
849 if (Assert.ASSERTS_ENABLED) {
850 int index = linearSearch(methods, name, signature);
851 if (index != -1) {
852 throw new DebuggerException("binary search bug: should have found entry " + index);
853 }
854 }
855 return null;
856 } else if (res < 0) {
857 l = mid + 1;
858 } else {
859 h = mid - 1;
860 }
861 }
862 if (Assert.ASSERTS_ENABLED) {
863 int index = linearSearch(methods, name, signature);
864 if (index != -1) {
865 throw new DebuggerException("binary search bug: should have found entry " + index);
866 }
867 }
868 return null;
869 }
870
871 private static int linearSearch(ObjArray methods, Symbol name, Symbol signature) {
872 int len = (int) methods.getLength();
873 for (int index = 0; index < len; index++) {
874 Method m = (Method) methods.getObjAt(index);
875 if (m.getSignature().equals(signature) && m.getName().equals(name)) {
876 return index;
877 }
878 }
879 return -1;
880 }
881 }