Mercurial > hg > truffle
annotate agent/src/share/classes/sun/jvm/hotspot/jdi/ReferenceTypeImpl.java @ 7402:fd74228fd5ca
8004076: Move _max_locals and _size_of_parameters to ConstMethod for better sharing.
Summary: Move _max_locals and _size_of_parameters to ConstMethod for better sharing.
Reviewed-by: coleenp, minqi, jrose
author | jiangli |
---|---|
date | Tue, 11 Dec 2012 12:41:31 -0500 |
parents | da91efe96a93 |
children | 29985fccf378 |
rev | line source |
---|---|
0 | 1 /* |
6203
04ade88d9712
6294277: java -Xdebug crashes on SourceDebugExtension attribute larger than 64K
fparain
parents:
3908
diff
changeset
|
2 * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. |
0 | 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 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
25 package sun.jvm.hotspot.jdi; | |
26 | |
27 import java.io.*; | |
28 | |
29 import com.sun.jdi.*; | |
30 | |
3908
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
2471
diff
changeset
|
31 import sun.jvm.hotspot.memory.SystemDictionary; |
0 | 32 import sun.jvm.hotspot.oops.Instance; |
33 import sun.jvm.hotspot.oops.InstanceKlass; | |
34 import sun.jvm.hotspot.oops.ArrayKlass; | |
35 import sun.jvm.hotspot.oops.JVMDIClassStatus; | |
36 import sun.jvm.hotspot.oops.Klass; | |
3908
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
2471
diff
changeset
|
37 import sun.jvm.hotspot.oops.ObjArray; |
0 | 38 import sun.jvm.hotspot.oops.Oop; |
39 import sun.jvm.hotspot.oops.Symbol; | |
40 import sun.jvm.hotspot.oops.DefaultHeapVisitor; | |
41 import sun.jvm.hotspot.utilities.Assert; | |
42 | |
43 import java.util.*; | |
44 import java.lang.ref.SoftReference; | |
45 | |
46 public abstract class ReferenceTypeImpl extends TypeImpl | |
47 implements ReferenceType { | |
48 protected Klass saKlass; // This can be an InstanceKlass or an ArrayKlass | |
49 protected Symbol typeNameSymbol; // This is used in vm.classesByName to speedup search | |
50 private int modifiers = -1; | |
51 private String signature = null; | |
52 private SoftReference sdeRef = null; | |
53 private SoftReference fieldsCache; | |
54 private SoftReference allFieldsCache; | |
55 private SoftReference methodsCache; | |
56 private SoftReference allMethodsCache; | |
57 private SoftReference nestedTypesCache; | |
3908
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
2471
diff
changeset
|
58 private SoftReference methodInvokesCache; |
0 | 59 |
60 /* to mark when no info available */ | |
61 static final SDE NO_SDE_INFO_MARK = new SDE(); | |
62 | |
63 protected ReferenceTypeImpl(VirtualMachine aVm, sun.jvm.hotspot.oops.Klass klass) { | |
64 super(aVm); | |
65 saKlass = klass; | |
66 typeNameSymbol = saKlass.getName(); | |
67 if (Assert.ASSERTS_ENABLED) { | |
68 Assert.that(typeNameSymbol != null, "null type name for a Klass"); | |
69 } | |
70 } | |
71 | |
72 Symbol typeNameAsSymbol() { | |
73 return typeNameSymbol; | |
74 } | |
75 | |
76 Method getMethodMirror(sun.jvm.hotspot.oops.Method ref) { | |
77 // SA creates new Method objects when they are referenced which means | |
78 // that the incoming object might not be the same object as on our | |
79 // even though it is the same method. So do an address compare by | |
80 // calling equals rather than just reference compare. | |
81 Iterator it = methods().iterator(); | |
82 while (it.hasNext()) { | |
83 MethodImpl method = (MethodImpl)it.next(); | |
84 if (ref.equals(method.ref())) { | |
85 return method; | |
86 } | |
87 } | |
3908
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
2471
diff
changeset
|
88 if (ref.getMethodHolder().equals(SystemDictionary.getMethodHandleKlass())) { |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
2471
diff
changeset
|
89 // invoke methods are generated as needed, so make mirrors as needed |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
2471
diff
changeset
|
90 List mis = null; |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
2471
diff
changeset
|
91 if (methodInvokesCache == null) { |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
2471
diff
changeset
|
92 mis = new ArrayList(); |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
2471
diff
changeset
|
93 methodInvokesCache = new SoftReference(mis); |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
2471
diff
changeset
|
94 } else { |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
2471
diff
changeset
|
95 mis = (List)methodInvokesCache.get(); |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
2471
diff
changeset
|
96 } |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
2471
diff
changeset
|
97 it = mis.iterator(); |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
2471
diff
changeset
|
98 while (it.hasNext()) { |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
2471
diff
changeset
|
99 MethodImpl method = (MethodImpl)it.next(); |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
2471
diff
changeset
|
100 if (ref.equals(method.ref())) { |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
2471
diff
changeset
|
101 return method; |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
2471
diff
changeset
|
102 } |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
2471
diff
changeset
|
103 } |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
2471
diff
changeset
|
104 |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
2471
diff
changeset
|
105 MethodImpl method = MethodImpl.createMethodImpl(vm, this, ref); |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
2471
diff
changeset
|
106 mis.add(method); |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
2471
diff
changeset
|
107 return method; |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
2471
diff
changeset
|
108 } |
0 | 109 throw new IllegalArgumentException("Invalid method id: " + ref); |
110 } | |
111 | |
112 public boolean equals(Object obj) { | |
113 if ((obj != null) && (obj instanceof ReferenceTypeImpl)) { | |
114 ReferenceTypeImpl other = (ReferenceTypeImpl)obj; | |
115 return (ref().equals(other.ref())) && | |
116 (vm.equals(other.virtualMachine())); | |
117 } else { | |
118 return false; | |
119 } | |
120 } | |
121 | |
122 public int hashCode() { | |
123 return saKlass.hashCode(); | |
124 } | |
125 | |
2471
37be97a58393
7010849: 5/5 Extraneous javac source/target options when building sa-jdi
andrew
parents:
1552
diff
changeset
|
126 public int compareTo(ReferenceType refType) { |
0 | 127 /* |
128 * Note that it is critical that compareTo() == 0 | |
129 * implies that equals() == true. Otherwise, TreeSet | |
130 * will collapse classes. | |
131 * | |
132 * (Classes of the same name loaded by different class loaders | |
133 * or in different VMs must not return 0). | |
134 */ | |
2471
37be97a58393
7010849: 5/5 Extraneous javac source/target options when building sa-jdi
andrew
parents:
1552
diff
changeset
|
135 ReferenceTypeImpl other = (ReferenceTypeImpl)refType; |
0 | 136 int comp = name().compareTo(other.name()); |
137 if (comp == 0) { | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6203
diff
changeset
|
138 Klass rf1 = ref(); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6203
diff
changeset
|
139 Klass rf2 = other.ref(); |
0 | 140 // optimize for typical case: refs equal and VMs equal |
141 if (rf1.equals(rf2)) { | |
142 // sequenceNumbers are always positive | |
143 comp = vm.sequenceNumber - | |
144 ((VirtualMachineImpl)(other.virtualMachine())).sequenceNumber; | |
145 } else { | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6203
diff
changeset
|
146 comp = rf1.getAddress().minus(rf2.getAddress()) < 0? -1 : 1; |
0 | 147 } |
148 } | |
149 return comp; | |
150 } | |
151 | |
152 public String signature() { | |
153 if (signature == null) { | |
154 signature = saKlass.signature(); | |
155 } | |
156 return signature; | |
157 } | |
158 | |
159 // refer to JvmtiEnv::GetClassSignature. | |
160 // null is returned for array klasses. | |
161 public String genericSignature() { | |
162 if (saKlass instanceof ArrayKlass) { | |
163 return null; | |
164 } else { | |
165 Symbol genSig = ((InstanceKlass)saKlass).getGenericSignature(); | |
166 return (genSig != null)? genSig.asString() : null; | |
167 } | |
168 } | |
169 | |
170 public ClassLoaderReference classLoader() { | |
171 Instance xx = (Instance)(((InstanceKlass)saKlass).getClassLoader()); | |
172 return (ClassLoaderReferenceImpl)vm.classLoaderMirror(xx); | |
173 } | |
174 | |
175 public boolean isPublic() { | |
176 return((modifiers() & VMModifiers.PUBLIC) != 0); | |
177 } | |
178 | |
179 public boolean isProtected() { | |
180 return((modifiers() & VMModifiers.PROTECTED) != 0); | |
181 } | |
182 | |
183 public boolean isPrivate() { | |
184 return((modifiers() & VMModifiers.PRIVATE) != 0); | |
185 } | |
186 | |
187 public boolean isPackagePrivate() { | |
188 return !isPublic() && !isPrivate() && !isProtected(); | |
189 } | |
190 | |
191 public boolean isAbstract() { | |
192 return((modifiers() & VMModifiers.ABSTRACT) != 0); | |
193 } | |
194 | |
195 public boolean isFinal() { | |
196 return((modifiers() & VMModifiers.FINAL) != 0); | |
197 } | |
198 | |
199 public boolean isStatic() { | |
200 return((modifiers() & VMModifiers.STATIC) != 0); | |
201 } | |
202 | |
203 public boolean isPrepared() { | |
204 return (saKlass.getClassStatus() & JVMDIClassStatus.PREPARED) != 0; | |
205 } | |
206 | |
207 final void checkPrepared() throws ClassNotPreparedException { | |
208 if (! isPrepared()) { | |
209 throw new ClassNotPreparedException(); | |
210 } | |
211 } | |
212 | |
213 public boolean isVerified() { | |
214 return (saKlass.getClassStatus() & JVMDIClassStatus.VERIFIED) != 0; | |
215 } | |
216 | |
217 public boolean isInitialized() { | |
218 return (saKlass.getClassStatus() & JVMDIClassStatus.INITIALIZED) != 0; | |
219 } | |
220 | |
221 public boolean failedToInitialize() { | |
222 return (saKlass.getClassStatus() & JVMDIClassStatus.ERROR) != 0; | |
223 } | |
224 | |
225 private boolean isThrowableBacktraceField(sun.jvm.hotspot.oops.Field fld) { | |
226 // refer to JvmtiEnv::GetClassFields in jvmtiEnv.cpp. | |
227 // We want to filter out java.lang.Throwable.backtrace (see 4446677). | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6203
diff
changeset
|
228 // It contains some Method*s that aren't quite real Objects. |
0 | 229 if (fld.getFieldHolder().getName().equals(vm.javaLangThrowable()) && |
230 fld.getID().getName().equals("backtrace")) { | |
231 return true; | |
232 } else { | |
233 return false; | |
234 } | |
235 } | |
236 | |
237 public final List fields() throws ClassNotPreparedException { | |
238 List fields = (fieldsCache != null)? (List) fieldsCache.get() : null; | |
239 if (fields == null) { | |
240 checkPrepared(); | |
241 if (saKlass instanceof ArrayKlass) { | |
242 fields = new ArrayList(0); | |
243 } else { | |
244 // Get a list of the sa Field types | |
245 List saFields = ((InstanceKlass)saKlass).getImmediateFields(); | |
246 | |
247 // Create a list of our Field types | |
248 int len = saFields.size(); | |
249 fields = new ArrayList(len); | |
250 for (int ii = 0; ii < len; ii++) { | |
251 sun.jvm.hotspot.oops.Field curField = (sun.jvm.hotspot.oops.Field)saFields.get(ii); | |
252 if (! isThrowableBacktraceField(curField)) { | |
253 fields.add(new FieldImpl(vm, this, curField)); | |
254 } | |
255 } | |
256 } | |
257 fields = Collections.unmodifiableList(fields); | |
258 fieldsCache = new SoftReference(fields); | |
259 } | |
260 return fields; | |
261 } | |
262 | |
263 public final List allFields() throws ClassNotPreparedException { | |
264 List allFields = (allFieldsCache != null)? (List) allFieldsCache.get() : null; | |
265 if (allFields == null) { | |
266 checkPrepared(); | |
267 if (saKlass instanceof ArrayKlass) { | |
268 // is 'length' a field of array klasses? To maintain | |
269 // consistency with JVMDI-JDI we return 0 size. | |
270 allFields = new ArrayList(0); | |
271 } else { | |
272 List saFields; | |
273 | |
274 // Get a list of the sa Field types | |
275 saFields = ((InstanceKlass)saKlass).getAllFields(); | |
276 | |
277 // Create a list of our Field types | |
278 int len = saFields.size(); | |
279 allFields = new ArrayList(len); | |
280 for (int ii = 0; ii < len; ii++) { | |
281 sun.jvm.hotspot.oops.Field curField = (sun.jvm.hotspot.oops.Field)saFields.get(ii); | |
282 if (! isThrowableBacktraceField(curField)) { | |
283 allFields.add(new FieldImpl(vm, vm.referenceType(curField.getFieldHolder()), curField)); | |
284 } | |
285 } | |
286 } | |
287 allFields = Collections.unmodifiableList(allFields); | |
288 allFieldsCache = new SoftReference(allFields); | |
289 } | |
290 return allFields; | |
291 } | |
292 | |
293 abstract List inheritedTypes(); | |
294 | |
295 void addVisibleFields(List visibleList, Map visibleTable, List ambiguousNames) { | |
296 List list = visibleFields(); | |
297 Iterator iter = list.iterator(); | |
298 while (iter.hasNext()) { | |
299 Field field = (Field)iter.next(); | |
300 String name = field.name(); | |
301 if (!ambiguousNames.contains(name)) { | |
302 Field duplicate = (Field)visibleTable.get(name); | |
303 if (duplicate == null) { | |
304 visibleList.add(field); | |
305 visibleTable.put(name, field); | |
306 } else if (!field.equals(duplicate)) { | |
307 ambiguousNames.add(name); | |
308 visibleTable.remove(name); | |
309 visibleList.remove(duplicate); | |
310 } else { | |
311 // identical field from two branches; do nothing | |
312 } | |
313 } | |
314 } | |
315 } | |
316 | |
317 public final List visibleFields() throws ClassNotPreparedException { | |
318 checkPrepared(); | |
319 /* | |
320 * Maintain two different collections of visible fields. The | |
321 * list maintains a reasonable order for return. The | |
322 * hash map provides an efficient way to lookup visible fields | |
323 * by name, important for finding hidden or ambiguous fields. | |
324 */ | |
325 List visibleList = new ArrayList(); | |
326 Map visibleTable = new HashMap(); | |
327 | |
328 /* Track fields removed from above collection due to ambiguity */ | |
329 List ambiguousNames = new ArrayList(); | |
330 | |
331 /* Add inherited, visible fields */ | |
332 List types = inheritedTypes(); | |
333 Iterator iter = types.iterator(); | |
334 while (iter.hasNext()) { | |
335 /* | |
336 * TO DO: Be defensive and check for cyclic interface inheritance | |
337 */ | |
338 ReferenceTypeImpl type = (ReferenceTypeImpl)iter.next(); | |
339 type.addVisibleFields(visibleList, visibleTable, ambiguousNames); | |
340 } | |
341 | |
342 /* | |
343 * Insert fields from this type, removing any inherited fields they | |
344 * hide. | |
345 */ | |
346 List retList = new ArrayList(fields()); | |
347 iter = retList.iterator(); | |
348 while (iter.hasNext()) { | |
349 Field field = (Field)iter.next(); | |
350 Field hidden = (Field)visibleTable.get(field.name()); | |
351 if (hidden != null) { | |
352 visibleList.remove(hidden); | |
353 } | |
354 } | |
355 retList.addAll(visibleList); | |
356 return retList; | |
357 } | |
358 | |
359 public final Field fieldByName(String fieldName) throws ClassNotPreparedException { | |
360 java.util.List searchList; | |
361 Field f; | |
362 | |
363 // visibleFields calls checkPrepared | |
364 searchList = visibleFields(); | |
365 | |
366 for (int i=0; i<searchList.size(); i++) { | |
367 f = (Field)searchList.get(i); | |
368 | |
369 if (f.name().equals(fieldName)) { | |
370 return f; | |
371 } | |
372 } | |
373 //throw new NoSuchFieldException("Field '" + fieldName + "' not found in " + name()); | |
374 return null; | |
375 } | |
376 | |
377 public final List methods() throws ClassNotPreparedException { | |
378 List methods = (methodsCache != null)? (List) methodsCache.get() : null; | |
379 if (methods == null) { | |
380 checkPrepared(); | |
381 if (saKlass instanceof ArrayKlass) { | |
382 methods = new ArrayList(0); | |
383 } else { | |
384 List saMethods; | |
385 // Get a list of the SA Method types | |
386 saMethods = ((InstanceKlass)saKlass).getImmediateMethods(); | |
387 | |
388 // Create a list of our MethodImpl types | |
389 int len = saMethods.size(); | |
390 methods = new ArrayList(len); | |
391 for (int ii = 0; ii < len; ii++) { | |
392 methods.add(MethodImpl.createMethodImpl(vm, this, (sun.jvm.hotspot.oops.Method)saMethods.get(ii))); | |
393 } | |
394 } | |
395 methods = Collections.unmodifiableList(methods); | |
396 methodsCache = new SoftReference(methods); | |
397 } | |
398 return methods; | |
399 } | |
400 | |
401 abstract List getAllMethods(); | |
402 public final List allMethods() throws ClassNotPreparedException { | |
403 List allMethods = (allMethodsCache != null)? (List) allMethodsCache.get() : null; | |
404 if (allMethods == null) { | |
405 checkPrepared(); | |
406 allMethods = Collections.unmodifiableList(getAllMethods()); | |
407 allMethodsCache = new SoftReference(allMethods); | |
408 } | |
409 return allMethods; | |
410 } | |
411 | |
412 /* | |
413 * Utility method used by subclasses to build lists of visible | |
414 * methods. | |
415 */ | |
416 void addToMethodMap(Map methodMap, List methodList) { | |
417 Iterator iter = methodList.iterator(); | |
418 while (iter.hasNext()) { | |
419 Method method = (Method)iter.next(); | |
420 methodMap.put(method.name().concat(method.signature()), method); | |
421 } | |
422 } | |
423 | |
424 abstract void addVisibleMethods(Map methodMap); | |
425 public final List visibleMethods() throws ClassNotPreparedException { | |
426 checkPrepared(); | |
427 /* | |
428 * Build a collection of all visible methods. The hash | |
429 * map allows us to do this efficiently by keying on the | |
430 * concatenation of name and signature. | |
431 */ | |
432 //System.out.println("jj: RTI: Calling addVisibleMethods for:" + this); | |
433 Map map = new HashMap(); | |
434 addVisibleMethods(map); | |
435 | |
436 /* | |
437 * ... but the hash map destroys order. Methods should be | |
438 * returned in a sensible order, as they are in allMethods(). | |
439 * So, start over with allMethods() and use the hash map | |
440 * to filter that ordered collection. | |
441 */ | |
442 //System.out.println("jj: RTI: Calling allMethods for:" + this); | |
443 | |
444 List list = new ArrayList(allMethods()); | |
445 //System.out.println("jj: allMethods = " + jjstr(list)); | |
446 //System.out.println("jj: map = " + map.toString()); | |
447 //System.out.println("jj: map = " + jjstr(map.values())); | |
448 list.retainAll(map.values()); | |
449 //System.out.println("jj: map = " + jjstr(list)); | |
450 //System.exit(0); | |
451 return list; | |
452 } | |
453 | |
454 static Object prev; | |
455 | |
456 static public String jjstr(Collection cc) { | |
457 StringBuffer buf = new StringBuffer(); | |
458 buf.append("["); | |
459 Iterator i = cc.iterator(); | |
460 boolean hasNext = i.hasNext(); | |
461 while (hasNext) { | |
462 Object o = i.next(); | |
463 if (prev == null) { | |
464 prev = o; | |
465 } else { | |
466 System.out.println("prev == curr?" + prev.equals(o)); | |
467 System.out.println("prev == curr?" + (prev == o)); | |
468 } | |
469 buf.append( o + "@" + o.hashCode()); | |
470 //buf.append( ((Object)o).toString()); | |
471 hasNext = i.hasNext(); | |
472 if (hasNext) | |
473 buf.append(", "); | |
474 } | |
475 | |
476 buf.append("]"); | |
477 return buf.toString(); | |
478 } | |
479 | |
480 public final List methodsByName(String name) throws ClassNotPreparedException { | |
481 // visibleMethods calls checkPrepared | |
482 List methods = visibleMethods(); | |
483 ArrayList retList = new ArrayList(methods.size()); | |
484 Iterator iter = methods.iterator(); | |
485 while (iter.hasNext()) { | |
486 Method candidate = (Method)iter.next(); | |
487 if (candidate.name().equals(name)) { | |
488 retList.add(candidate); | |
489 } | |
490 } | |
491 retList.trimToSize(); | |
492 return retList; | |
493 } | |
494 | |
495 public final List methodsByName(String name, String signature) throws ClassNotPreparedException { | |
496 // visibleMethods calls checkPrepared | |
497 List methods = visibleMethods(); | |
498 ArrayList retList = new ArrayList(methods.size()); | |
499 Iterator iter = methods.iterator(); | |
500 while (iter.hasNext()) { | |
501 Method candidate = (Method)iter.next(); | |
502 if (candidate.name().equals(name) && | |
503 candidate.signature().equals(signature)) { | |
504 retList.add(candidate); | |
505 } | |
506 } | |
507 retList.trimToSize(); | |
508 return retList; | |
509 } | |
510 | |
511 | |
512 List getInterfaces() { | |
513 List myInterfaces; | |
514 if (saKlass instanceof ArrayKlass) { | |
515 // Actually, JLS says arrays implement Cloneable and Serializable | |
516 // But, JVMDI-JDI just returns 0 interfaces for arrays. We follow | |
517 // the same for consistency. | |
518 myInterfaces = new ArrayList(0); | |
519 } else { | |
520 // Get a list of the sa InstanceKlass types | |
521 List saInterfaces = ((InstanceKlass)saKlass).getDirectImplementedInterfaces(); | |
522 | |
523 // Create a list of our InterfaceTypes | |
524 int len = saInterfaces.size(); | |
525 myInterfaces = new ArrayList(len); | |
526 for (int ii = 0; ii < len; ii++) { | |
527 myInterfaces.add(new InterfaceTypeImpl(vm, (InstanceKlass)saInterfaces.get(ii))); | |
528 } | |
529 } | |
530 return myInterfaces; | |
531 } | |
532 | |
533 public final List nestedTypes() { | |
534 List nestedTypes = (nestedTypesCache != null)? (List) nestedTypesCache.get() : null; | |
535 if (nestedTypes == null) { | |
536 if (saKlass instanceof ArrayKlass) { | |
537 nestedTypes = new ArrayList(0); | |
538 } else { | |
539 ClassLoaderReference cl = classLoader(); | |
540 List classes = null; | |
541 if (cl != null) { | |
542 classes = cl.visibleClasses(); | |
543 } else { | |
544 classes = vm.bootstrapClasses(); | |
545 } | |
546 nestedTypes = new ArrayList(); | |
547 Iterator iter = classes.iterator(); | |
548 while (iter.hasNext()) { | |
549 ReferenceTypeImpl refType = (ReferenceTypeImpl)iter.next(); | |
550 Symbol candidateName = refType.ref().getName(); | |
551 if (((InstanceKlass)saKlass).isInnerOrLocalClassName(candidateName)) { | |
552 nestedTypes.add(refType); | |
553 } | |
554 } | |
555 } | |
556 nestedTypes = Collections.unmodifiableList(nestedTypes); | |
557 nestedTypesCache = new SoftReference(nestedTypes); | |
558 } | |
559 return nestedTypes; | |
560 } | |
561 | |
562 public Value getValue(Field sig) { | |
563 List list = new ArrayList(1); | |
564 list.add(sig); | |
565 Map map = getValues(list); | |
566 return(Value)map.get(sig); | |
567 } | |
568 | |
569 /** | |
570 * Returns a map of field values | |
571 */ | |
572 public Map getValues(List theFields) { | |
573 //validateMirrors(); | |
574 int size = theFields.size(); | |
575 Map map = new HashMap(size); | |
576 for (int ii=0; ii<size; ii++) { | |
577 FieldImpl fieldImpl = (FieldImpl)theFields.get(ii); | |
578 | |
579 validateFieldAccess(fieldImpl); | |
580 // Do more validation specific to ReferenceType field getting | |
581 if (!fieldImpl.isStatic()) { | |
582 throw new IllegalArgumentException( | |
583 "Attempt to use non-static field with ReferenceType: " + | |
584 fieldImpl.name()); | |
585 } | |
586 map.put(fieldImpl, fieldImpl.getValue()); | |
587 } | |
588 return map; | |
589 } | |
590 | |
591 void validateFieldAccess(Field field) { | |
592 /* | |
593 * Field must be in this object's class, a superclass, or | |
594 * implemented interface | |
595 */ | |
596 ReferenceTypeImpl declType = (ReferenceTypeImpl)field.declaringType(); | |
597 if (!declType.isAssignableFrom(this)) { | |
598 throw new IllegalArgumentException("Invalid field"); | |
599 } | |
600 } | |
601 | |
602 public ClassObjectReference classObject() { | |
603 return vm.classObjectMirror(ref().getJavaMirror()); | |
604 } | |
605 | |
606 SDE.Stratum stratum(String stratumID) { | |
607 SDE sde = sourceDebugExtensionInfo(); | |
608 if (!sde.isValid()) { | |
609 sde = NO_SDE_INFO_MARK; | |
610 } | |
611 return sde.stratum(stratumID); | |
612 } | |
613 | |
614 public String sourceName() throws AbsentInformationException { | |
615 return (String)(sourceNames(vm.getDefaultStratum()).get(0)); | |
616 } | |
617 | |
618 public List sourceNames(String stratumID) | |
619 throws AbsentInformationException { | |
620 SDE.Stratum stratum = stratum(stratumID); | |
621 if (stratum.isJava()) { | |
622 List result = new ArrayList(1); | |
623 result.add(baseSourceName()); | |
624 return result; | |
625 } | |
626 return stratum.sourceNames(this); | |
627 } | |
628 | |
629 public List sourcePaths(String stratumID) | |
630 throws AbsentInformationException { | |
631 SDE.Stratum stratum = stratum(stratumID); | |
632 if (stratum.isJava()) { | |
633 List result = new ArrayList(1); | |
634 result.add(baseSourceDir() + baseSourceName()); | |
635 return result; | |
636 } | |
637 return stratum.sourcePaths(this); | |
638 } | |
639 | |
640 String baseSourceName() throws AbsentInformationException { | |
641 if (saKlass instanceof ArrayKlass) { | |
642 throw new AbsentInformationException(); | |
643 } | |
644 Symbol sym = ((InstanceKlass)saKlass).getSourceFileName(); | |
645 if (sym != null) { | |
646 return sym.asString(); | |
647 } else { | |
648 throw new AbsentInformationException(); | |
649 } | |
650 } | |
651 | |
652 String baseSourcePath() throws AbsentInformationException { | |
653 return baseSourceDir() + baseSourceName(); | |
654 } | |
655 | |
656 String baseSourceDir() { | |
657 String typeName = name(); | |
658 StringBuffer sb = new StringBuffer(typeName.length() + 10); | |
659 int index = 0; | |
660 int nextIndex; | |
661 | |
662 while ((nextIndex = typeName.indexOf('.', index)) > 0) { | |
663 sb.append(typeName.substring(index, nextIndex)); | |
664 sb.append(java.io.File.separatorChar); | |
665 index = nextIndex + 1; | |
666 } | |
667 return sb.toString(); | |
668 } | |
669 | |
670 public String sourceDebugExtension() | |
671 throws AbsentInformationException { | |
672 if (!vm.canGetSourceDebugExtension()) { | |
673 throw new UnsupportedOperationException(); | |
674 } | |
675 SDE sde = sourceDebugExtensionInfo(); | |
676 if (sde == NO_SDE_INFO_MARK) { | |
677 throw new AbsentInformationException(); | |
678 } | |
679 return sde.sourceDebugExtension; | |
680 } | |
681 | |
682 private SDE sourceDebugExtensionInfo() { | |
683 if (!vm.canGetSourceDebugExtension()) { | |
684 return NO_SDE_INFO_MARK; | |
685 } | |
686 SDE sde = null; | |
687 sde = (sdeRef == null) ? null : (SDE)sdeRef.get(); | |
688 if (sde == null) { | |
689 String extension = null; | |
690 if (saKlass instanceof InstanceKlass) { | |
6203
04ade88d9712
6294277: java -Xdebug crashes on SourceDebugExtension attribute larger than 64K
fparain
parents:
3908
diff
changeset
|
691 extension = ((InstanceKlass)saKlass).getSourceDebugExtension(); |
0 | 692 } |
693 if (extension == null) { | |
694 sde = NO_SDE_INFO_MARK; | |
695 } else { | |
696 sde = new SDE(extension); | |
697 } | |
698 sdeRef = new SoftReference(sde); | |
699 } | |
700 return sde; | |
701 } | |
702 | |
703 public List availableStrata() { | |
704 SDE sde = sourceDebugExtensionInfo(); | |
705 if (sde.isValid()) { | |
706 return sde.availableStrata(); | |
707 } else { | |
708 List strata = new ArrayList(); | |
709 strata.add(SDE.BASE_STRATUM_NAME); | |
710 return strata; | |
711 } | |
712 } | |
713 | |
714 /** | |
715 * Always returns non-null stratumID | |
716 */ | |
717 public String defaultStratum() { | |
718 SDE sdei = sourceDebugExtensionInfo(); | |
719 if (sdei.isValid()) { | |
720 return sdei.defaultStratumId; | |
721 } else { | |
722 return SDE.BASE_STRATUM_NAME; | |
723 } | |
724 } | |
725 | |
726 public final int modifiers() { | |
727 if (modifiers == -1) { | |
728 modifiers = getModifiers(); | |
729 } | |
730 return modifiers; | |
731 } | |
732 | |
733 // new method since 1.6. | |
734 // Real body will be supplied later. | |
735 public List instances(long maxInstances) { | |
736 if (!vm.canGetInstanceInfo()) { | |
737 throw new UnsupportedOperationException( | |
738 "target does not support getting instances"); | |
739 } | |
740 | |
741 if (maxInstances < 0) { | |
742 throw new IllegalArgumentException("maxInstances is less than zero: " | |
743 + maxInstances); | |
744 } | |
745 | |
746 final List objects = new ArrayList(0); | |
747 if (isAbstract() || (this instanceof InterfaceType)) { | |
748 return objects; | |
749 } | |
750 | |
751 final Klass givenKls = this.ref(); | |
752 final long max = maxInstances; | |
753 vm.saObjectHeap().iterate(new DefaultHeapVisitor() { | |
754 private long instCount=0; | |
755 public boolean doObj(Oop oop) { | |
756 if (givenKls.equals(oop.getKlass())) { | |
757 objects.add(vm.objectMirror(oop)); | |
758 instCount++; | |
759 } | |
760 if (max > 0 && instCount >= max) { | |
761 return true; | |
762 } | |
763 return false; | |
764 } | |
765 }); | |
766 return objects; | |
767 } | |
768 | |
769 int getModifiers() { | |
770 return (int) saKlass.getClassModifiers(); | |
771 } | |
772 | |
773 public List allLineLocations() | |
774 throws AbsentInformationException { | |
775 return allLineLocations(vm.getDefaultStratum(), null); | |
776 } | |
777 | |
778 public List allLineLocations(String stratumID, String sourceName) | |
779 throws AbsentInformationException { | |
780 checkPrepared(); | |
781 boolean someAbsent = false; // A method that should have info, didn't | |
782 SDE.Stratum stratum = stratum(stratumID); | |
783 List list = new ArrayList(); // location list | |
784 | |
785 for (Iterator iter = methods().iterator(); iter.hasNext(); ) { | |
786 MethodImpl method = (MethodImpl)iter.next(); | |
787 try { | |
788 list.addAll( | |
789 method.allLineLocations(stratum.id(), sourceName)); | |
790 } catch(AbsentInformationException exc) { | |
791 someAbsent = true; | |
792 } | |
793 } | |
794 | |
795 // If we retrieved no line info, and at least one of the methods | |
796 // should have had some (as determined by an | |
797 // AbsentInformationException being thrown) then we rethrow | |
798 // the AbsentInformationException. | |
799 if (someAbsent && list.size() == 0) { | |
800 throw new AbsentInformationException(); | |
801 } | |
802 return list; | |
803 } | |
804 | |
805 public List locationsOfLine(int lineNumber) | |
806 throws AbsentInformationException { | |
807 return locationsOfLine(vm.getDefaultStratum(), | |
808 null, | |
809 lineNumber); | |
810 } | |
811 | |
812 public List locationsOfLine(String stratumID, | |
813 String sourceName, | |
814 int lineNumber) | |
815 throws AbsentInformationException { | |
816 checkPrepared(); | |
817 // A method that should have info, didn't | |
818 boolean someAbsent = false; | |
819 // A method that should have info, did | |
820 boolean somePresent = false; | |
821 List methods = methods(); | |
822 SDE.Stratum stratum = stratum(stratumID); | |
823 | |
824 List list = new ArrayList(); | |
825 | |
826 Iterator iter = methods.iterator(); | |
827 while(iter.hasNext()) { | |
828 MethodImpl method = (MethodImpl)iter.next(); | |
829 // eliminate native and abstract to eliminate | |
830 // false positives | |
831 if (!method.isAbstract() && | |
832 !method.isNative()) { | |
833 try { | |
834 list.addAll( | |
835 method.locationsOfLine(stratum.id(), | |
836 sourceName, | |
837 lineNumber)); | |
838 somePresent = true; | |
839 } catch(AbsentInformationException exc) { | |
840 someAbsent = true; | |
841 } | |
842 } | |
843 } | |
844 if (someAbsent && !somePresent) { | |
845 throw new AbsentInformationException(); | |
846 } | |
847 return list; | |
848 } | |
849 | |
850 Klass ref() { | |
851 return saKlass; | |
852 } | |
853 | |
854 | |
855 /* | |
856 * Return true if an instance of this type | |
857 * can be assigned to a variable of the given type | |
858 */ | |
859 abstract boolean isAssignableTo(ReferenceType type); | |
860 | |
861 boolean isAssignableFrom(ReferenceType type) { | |
862 return ((ReferenceTypeImpl)type).isAssignableTo(this); | |
863 } | |
864 | |
865 boolean isAssignableFrom(ObjectReference object) { | |
866 return object == null || | |
867 isAssignableFrom(object.referenceType()); | |
868 } | |
869 | |
870 int indexOf(Method method) { | |
871 // Make sure they're all here - the obsolete method | |
872 // won't be found and so will have index -1 | |
873 return methods().indexOf(method); | |
874 } | |
875 | |
876 int indexOf(Field field) { | |
877 // Make sure they're all here | |
878 return fields().indexOf(field); | |
879 } | |
880 | |
881 private static boolean isPrimitiveArray(String signature) { | |
882 int i = signature.lastIndexOf('['); | |
883 /* | |
884 * TO DO: Centralize JNI signature knowledge. | |
885 * | |
886 * Ref: | |
887 * jdk1.4/doc/guide/jpda/jdi/com/sun/jdi/doc-files/signature.html | |
888 */ | |
889 boolean isPA; | |
890 if (i < 0) { | |
891 isPA = false; | |
892 } else { | |
893 char c = signature.charAt(i + 1); | |
894 isPA = (c != 'L'); | |
895 } | |
896 return isPA; | |
897 } | |
898 | |
899 Type findType(String signature) throws ClassNotLoadedException { | |
900 Type type; | |
901 if (signature.length() == 1) { | |
902 /* OTI FIX: Must be a primitive type or the void type */ | |
903 char sig = signature.charAt(0); | |
904 if (sig == 'V') { | |
905 type = vm.theVoidType(); | |
906 } else { | |
907 type = vm.primitiveTypeMirror(sig); | |
908 } | |
909 } else { | |
910 // Must be a reference type. | |
911 ClassLoaderReferenceImpl loader = | |
912 (ClassLoaderReferenceImpl)classLoader(); | |
913 if ((loader == null) || | |
914 (isPrimitiveArray(signature)) //Work around 4450091 | |
915 ) { | |
916 // Caller wants type of boot class field | |
917 type = vm.findBootType(signature); | |
918 } else { | |
919 // Caller wants type of non-boot class field | |
920 type = loader.findType(signature); | |
921 } | |
922 } | |
923 return type; | |
924 } | |
925 | |
926 String loaderString() { | |
927 if (classLoader() != null) { | |
928 return "loaded by " + classLoader().toString(); | |
929 } else { | |
930 return "loaded by bootstrap loader"; | |
931 } | |
932 } | |
933 | |
934 long uniqueID() { | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6203
diff
changeset
|
935 return vm.getAddressValue(ref().getJavaMirror()); |
0 | 936 } |
937 | |
938 // new method since 1.6 | |
939 public int majorVersion() { | |
940 if (!vm.canGetClassFileVersion()) { | |
941 throw new UnsupportedOperationException("Cannot get class file version"); | |
942 } | |
943 return (int)((InstanceKlass)saKlass).majorVersion(); | |
944 } | |
945 | |
946 // new method since 1.6 | |
947 public int minorVersion() { | |
948 if (!vm.canGetClassFileVersion()) { | |
949 throw new UnsupportedOperationException("Cannot get class file version"); | |
950 } | |
951 return (int)((InstanceKlass)saKlass).minorVersion(); | |
952 } | |
953 | |
954 // new method since 1.6 | |
955 public int constantPoolCount() { | |
956 if (!vm.canGetConstantPool()) { | |
957 throw new UnsupportedOperationException("Cannot get constant pool"); | |
958 } | |
959 if (saKlass instanceof ArrayKlass) { | |
960 return 0; | |
961 } else { | |
962 return (int)((InstanceKlass)saKlass).getConstants().getLength(); | |
963 } | |
964 } | |
965 | |
966 // new method since 1.6 | |
967 public byte[] constantPool() { | |
968 if (!vm.canGetConstantPool()) { | |
969 throw new UnsupportedOperationException("Cannot get constant pool"); | |
970 } | |
971 if (this instanceof ArrayType || this instanceof PrimitiveType) { | |
972 byte bytes[] = new byte[0]; | |
973 return bytes; | |
974 } else { | |
975 ByteArrayOutputStream bs = new ByteArrayOutputStream(); | |
976 try { | |
977 ((InstanceKlass)saKlass).getConstants().writeBytes(bs); | |
978 } catch (IOException ex) { | |
979 ex.printStackTrace(); | |
980 byte bytes[] = new byte[0]; | |
981 return bytes; | |
982 } | |
983 return bs.toByteArray(); | |
984 } | |
985 } | |
986 } |