Mercurial > hg > truffle
annotate agent/src/share/classes/sun/jvm/hotspot/utilities/ObjectReader.java @ 3972:4f93f0d00802
7059019: G1: add G1 support to the SA
Summary: Extend the SA to recognize the G1CollectedHeap and implement any code that's needed by our serviceability tools (jmap, jinfo, jstack, etc.) that depend on the SA.
Reviewed-by: never, poonam, johnc
author | tonyp |
---|---|
date | Tue, 20 Sep 2011 09:59:59 -0400 |
parents | c18cbe5936b8 |
children | d8a240abb23a |
rev | line source |
---|---|
0 | 1 /* |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
2 * Copyright (c) 2002, 2007, 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.utilities; | |
26 | |
27 import java.lang.reflect.Modifier; | |
28 import java.util.*; | |
29 import sun.jvm.hotspot.debugger.*; | |
30 import sun.jvm.hotspot.oops.*; | |
31 import sun.jvm.hotspot.runtime.*; | |
32 import sun.jvm.hotspot.utilities.*; | |
33 | |
34 /** | |
35 * ObjectReader can "deserialize" objects from debuggee. | |
36 * | |
37 * Class Loading: | |
38 * | |
39 * ObjectReader loads classes using the given class loader. If no | |
40 * class loader is supplied, it uses a ProcImageClassLoader, which | |
41 * loads classes from debuggee core or process. | |
42 | |
43 * Object creation: | |
44 * | |
45 * This class uses no-arg constructor to construct objects. But if | |
46 * there is no no-arg constructor in a given class, then it tries to | |
47 * use other constructors with 'default' values - null for object | |
48 * types, 0, 0.0, false etc. for primitives. If this process fails to | |
49 * construct an instance (because of null checking by constructor or 0 | |
50 * being invalid for an int arg etc.), then null is returned. While | |
51 * constructing complete object graph 'null' is inserted silently on | |
52 * failure and the deserialization continues to construct best-effort | |
53 * object graph. | |
54 * | |
55 * Debug messages: | |
56 * | |
57 * The flag sun.jvm.hotspot.utilities.ObjectReader.DEBUG may be set to | |
58 * non-null to get debug error messages and stack traces. | |
59 * | |
60 * JDK version: | |
61 * | |
62 * JDK classes are loaded by bootstrap class loader and not by the | |
63 * supplied class loader or ProcImageClassLoader. This may create | |
64 * problems if a JDK class evolves. i.e., if SA runs a JDK version | |
65 * different from that of the debuggee, there is a possibility of | |
66 * schema change. It is recommended that the matching JDK version be | |
67 * used to run SA for proper object deserialization. | |
68 * | |
69 */ | |
70 | |
71 public class ObjectReader { | |
72 | |
73 private static final boolean DEBUG; | |
74 static { | |
75 DEBUG = System.getProperty("sun.jvm.hotspot.utilities.ObjectReader.DEBUG") != null; | |
76 } | |
77 | |
78 public ObjectReader(ClassLoader cl) { | |
79 this.cl = cl; | |
80 this.oopToObjMap = new HashMap(); | |
81 this.fieldMap = new HashMap(); | |
82 } | |
83 | |
84 public ObjectReader() { | |
85 this(new ProcImageClassLoader()); | |
86 } | |
87 | |
88 public Object readObject(Oop oop) throws ClassNotFoundException { | |
89 if (oop instanceof Instance) { | |
90 return readInstance((Instance) oop); | |
91 } else if (oop instanceof TypeArray){ | |
92 return readPrimitiveArray((TypeArray)oop); | |
93 } else if (oop instanceof ObjArray){ | |
94 return readObjectArray((ObjArray)oop); | |
95 } else { | |
96 return null; | |
97 } | |
98 } | |
99 | |
100 protected final Object getDefaultPrimitiveValue(Class clz) { | |
101 if (clz == Boolean.TYPE) { | |
102 return Boolean.FALSE; | |
103 } else if (clz == Character.TYPE) { | |
104 return new Character(' '); | |
105 } else if (clz == Byte.TYPE) { | |
106 return new Byte((byte) 0); | |
107 } else if (clz == Short.TYPE) { | |
108 return new Short((short) 0); | |
109 } else if (clz == Integer.TYPE) { | |
110 return new Integer(0); | |
111 } else if (clz == Long.TYPE) { | |
112 return new Long(0L); | |
113 } else if (clz == Float.TYPE) { | |
114 return new Float(0.0f); | |
115 } else if (clz == Double.TYPE) { | |
116 return new Double(0.0); | |
117 } else { | |
118 throw new RuntimeException("should not reach here!"); | |
119 } | |
120 } | |
121 | |
122 protected Symbol javaLangString; | |
123 protected Symbol javaLangString() { | |
124 if (javaLangString == null) { | |
125 javaLangString = VM.getVM().getSymbolTable().probe("java/lang/String"); | |
126 } | |
127 return javaLangString; | |
128 } | |
129 | |
130 public Object readInstance(Instance oop) throws ClassNotFoundException { | |
131 Object result = getFromObjTable(oop); | |
132 if (result == null) { | |
133 InstanceKlass kls = (InstanceKlass) oop.getKlass(); | |
134 // Handle java.lang.String instances differently. As part of JSR-133, fields of immutable | |
135 // classes have been made final. The algorithm below will not be able to read Strings from | |
136 // debuggee (can't use reflection to set final fields). But, need to read Strings is very | |
137 // important. FIXME: need a framework to handle many other special cases. | |
138 if (kls.getName().equals(javaLangString())) { | |
139 return OopUtilities.stringOopToString(oop); | |
140 } | |
141 | |
142 Class clz = readClass(kls); | |
143 try { | |
144 result = clz.newInstance(); | |
145 } catch (Exception ex) { | |
146 // no-arg constructor failed to create object. Let us try | |
147 // to call constructors one-by-one with default arguments | |
148 // (null for objects, 0/0.0 etc. for primitives) till we | |
149 // succeed or fail on all constructors. | |
150 | |
151 java.lang.reflect.Constructor[] ctrs = clz.getDeclaredConstructors(); | |
152 for (int n = 0; n < ctrs.length; n++) { | |
153 java.lang.reflect.Constructor c = ctrs[n]; | |
154 Class[] paramTypes = c.getParameterTypes(); | |
155 Object[] params = new Object[paramTypes.length]; | |
156 for (int i = 0; i < params.length; i++) { | |
157 if (paramTypes[i].isPrimitive()) { | |
158 params[i] = getDefaultPrimitiveValue(paramTypes[i]); | |
159 } | |
160 } | |
161 try { | |
162 c.setAccessible(true); | |
163 result = c.newInstance(params); | |
164 break; | |
165 } catch (Exception exp) { | |
166 if (DEBUG) { | |
167 System.err.println("Can't create object using " + c); | |
168 exp.printStackTrace(); | |
169 } | |
170 } | |
171 } | |
172 } | |
173 | |
174 if (result != null) { | |
175 putIntoObjTable(oop, result); | |
176 oop.iterate(new FieldSetter(result), false); | |
177 } | |
178 } | |
179 return result; | |
180 } | |
181 | |
182 public Object readPrimitiveArray(final TypeArray array) { | |
183 | |
184 Object result = getFromObjTable(array); | |
185 if (result == null) { | |
186 int length = (int) array.getLength(); | |
187 TypeArrayKlass klass = (TypeArrayKlass) array.getKlass(); | |
188 int type = (int) klass.getElementType(); | |
189 switch (type) { | |
190 case TypeArrayKlass.T_BOOLEAN: { | |
191 final boolean[] arrayObj = new boolean[length]; | |
192 array.iterate(new DefaultOopVisitor() { | |
193 public void doBoolean(BooleanField field, boolean isVMField) { | |
194 IndexableFieldIdentifier ifd = (IndexableFieldIdentifier) field.getID(); | |
195 arrayObj[ifd.getIndex()] = field.getValue(array); | |
196 } | |
197 }, false); | |
198 result = arrayObj; | |
199 } | |
200 break; | |
201 | |
202 case TypeArrayKlass.T_CHAR: { | |
203 final char[] arrayObj = new char[length]; | |
204 array.iterate(new DefaultOopVisitor() { | |
205 public void doChar(CharField field, boolean isVMField) { | |
206 IndexableFieldIdentifier ifd = (IndexableFieldIdentifier) field.getID(); | |
207 arrayObj[ifd.getIndex()] = field.getValue(array); | |
208 } | |
209 }, false); | |
210 result = arrayObj; | |
211 } | |
212 break; | |
213 | |
214 case TypeArrayKlass.T_FLOAT: { | |
215 final float[] arrayObj = new float[length]; | |
216 array.iterate(new DefaultOopVisitor() { | |
217 public void doFloat(FloatField field, boolean isVMField) { | |
218 IndexableFieldIdentifier ifd = (IndexableFieldIdentifier) field.getID(); | |
219 arrayObj[ifd.getIndex()] = field.getValue(array); | |
220 } | |
221 }, false); | |
222 result = arrayObj; | |
223 } | |
224 break; | |
225 | |
226 case TypeArrayKlass.T_DOUBLE: { | |
227 final double[] arrayObj = new double[length]; | |
228 array.iterate(new DefaultOopVisitor() { | |
229 public void doDouble(DoubleField field, boolean isVMField) { | |
230 IndexableFieldIdentifier ifd = (IndexableFieldIdentifier) field.getID(); | |
231 arrayObj[ifd.getIndex()] = field.getValue(array); | |
232 } | |
233 }, false); | |
234 result = arrayObj; | |
235 } | |
236 break; | |
237 | |
238 case TypeArrayKlass.T_BYTE: { | |
239 final byte[] arrayObj = new byte[length]; | |
240 array.iterate(new DefaultOopVisitor() { | |
241 public void doByte(ByteField field, boolean isVMField) { | |
242 IndexableFieldIdentifier ifd = (IndexableFieldIdentifier) field.getID(); | |
243 arrayObj[ifd.getIndex()] = field.getValue(array); | |
244 } | |
245 }, false); | |
246 result = arrayObj; | |
247 } | |
248 break; | |
249 | |
250 case TypeArrayKlass.T_SHORT: { | |
251 final short[] arrayObj = new short[length]; | |
252 array.iterate(new DefaultOopVisitor() { | |
253 public void doShort(ShortField field, boolean isVMField) { | |
254 IndexableFieldIdentifier ifd = (IndexableFieldIdentifier) field.getID(); | |
255 arrayObj[ifd.getIndex()] = field.getValue(array); | |
256 } | |
257 }, false); | |
258 result = arrayObj; | |
259 } | |
260 break; | |
261 | |
262 case TypeArrayKlass.T_INT: { | |
263 final int[] arrayObj = new int[length]; | |
264 array.iterate(new DefaultOopVisitor() { | |
265 public void doInt(IntField field, boolean isVMField) { | |
266 IndexableFieldIdentifier ifd = (IndexableFieldIdentifier) field.getID(); | |
267 arrayObj[ifd.getIndex()] = field.getValue(array); | |
268 } | |
269 }, false); | |
270 result = arrayObj; | |
271 } | |
272 break; | |
273 | |
274 case TypeArrayKlass.T_LONG: { | |
275 final long[] arrayObj = new long[length]; | |
276 array.iterate(new DefaultOopVisitor() { | |
277 public void doLong(LongField field, boolean isVMField) { | |
278 IndexableFieldIdentifier ifd = (IndexableFieldIdentifier) field.getID(); | |
279 arrayObj[ifd.getIndex()] = field.getValue(array); | |
280 } | |
281 }, false); | |
282 result = arrayObj; | |
283 } | |
284 break; | |
285 | |
286 default: | |
287 throw new RuntimeException("should not reach here!"); | |
288 } | |
289 | |
290 putIntoObjTable(array, result); | |
291 } | |
292 return result; | |
293 } | |
294 | |
295 protected final boolean isRobust(OopHandle handle) { | |
296 return RobustOopDeterminator.oopLooksValid(handle); | |
297 } | |
298 | |
299 public Object readObjectArray(final ObjArray array) throws ClassNotFoundException { | |
300 Object result = getFromObjTable(array); | |
301 if (result == null) { | |
302 int length = (int) array.getLength(); | |
303 ObjArrayKlass klass = (ObjArrayKlass) array.getKlass(); | |
304 Klass bottomKls = klass.getBottomKlass(); | |
305 Class bottomCls = null; | |
306 final int dimension = (int) klass.getDimension(); | |
307 int[] dimArray = null; | |
308 if (bottomKls instanceof InstanceKlass) { | |
309 bottomCls = readClass((InstanceKlass) bottomKls); | |
310 dimArray = new int[dimension]; | |
311 } else { // instanceof TypeArrayKlass | |
312 TypeArrayKlass botKls = (TypeArrayKlass) bottomKls; | |
313 dimArray = new int[dimension -1]; | |
314 } | |
315 // initialize the length | |
316 dimArray[0] = length; | |
317 final Object[] arrayObj = (Object[]) java.lang.reflect.Array.newInstance(bottomCls, dimArray); | |
318 putIntoObjTable(array, arrayObj); | |
319 result = arrayObj; | |
320 array.iterate(new DefaultOopVisitor() { | |
321 public void doOop(OopField field, boolean isVMField) { | |
322 OopHandle handle = field.getValueAsOopHandle(getObj()); | |
323 if (! isRobust(handle)) { | |
324 return; | |
325 } | |
326 | |
327 IndexableFieldIdentifier ifd = (IndexableFieldIdentifier) field.getID(); | |
328 try { | |
329 arrayObj[ifd.getIndex()] = readObject(field.getValue(getObj())); | |
330 } catch (Exception e) { | |
331 if (DEBUG) { | |
332 System.err.println("Array element set failed for " + ifd); | |
333 e.printStackTrace(); | |
334 } | |
335 } | |
336 } | |
337 }, false); | |
338 } | |
339 return result; | |
340 } | |
341 | |
342 protected class FieldSetter extends DefaultOopVisitor { | |
343 protected Object obj; | |
344 | |
345 public FieldSetter(Object obj) { | |
346 this.obj = obj; | |
347 } | |
348 | |
349 private void printFieldSetError(java.lang.reflect.Field f, Exception ex) { | |
350 if (DEBUG) { | |
351 if (f != null) System.err.println("Field set failed for " + f); | |
352 ex.printStackTrace(); | |
353 } | |
354 } | |
355 | |
356 // Callback methods for each field type in an object | |
357 public void doOop(OopField field, boolean isVMField) { | |
358 OopHandle handle = field.getValueAsOopHandle(getObj()); | |
359 if (! isRobust(handle) ) { | |
360 return; | |
361 } | |
362 | |
363 java.lang.reflect.Field f = null; | |
364 try { | |
365 f = readField(field); | |
366 if (Modifier.isFinal(f.getModifiers())) return; | |
367 f.setAccessible(true); | |
368 f.set(obj, readObject(field.getValue(getObj()))); | |
369 } catch (Exception ex) { | |
370 printFieldSetError(f, ex); | |
371 } | |
372 } | |
373 | |
374 public void doByte(ByteField field, boolean isVMField) { | |
375 java.lang.reflect.Field f = null; | |
376 try { | |
377 f = readField(field); | |
378 if (Modifier.isFinal(f.getModifiers())) return; | |
379 f.setAccessible(true); | |
380 f.setByte(obj, field.getValue(getObj())); | |
381 } catch (Exception ex) { | |
382 printFieldSetError(f, ex); | |
383 } | |
384 } | |
385 | |
386 public void doChar(CharField field, boolean isVMField) { | |
387 java.lang.reflect.Field f = null; | |
388 try { | |
389 f = readField(field); | |
390 if (Modifier.isFinal(f.getModifiers())) return; | |
391 f.setAccessible(true); | |
392 f.setChar(obj, field.getValue(getObj())); | |
393 } catch (Exception ex) { | |
394 printFieldSetError(f, ex); | |
395 } | |
396 } | |
397 | |
398 public void doBoolean(BooleanField field, boolean isVMField) { | |
399 java.lang.reflect.Field f = null; | |
400 try { | |
401 f = readField(field); | |
402 if (Modifier.isFinal(f.getModifiers())) return; | |
403 f.setAccessible(true); | |
404 f.setBoolean(obj, field.getValue(getObj())); | |
405 } catch (Exception ex) { | |
406 printFieldSetError(f, ex); | |
407 } | |
408 } | |
409 | |
410 public void doShort(ShortField field, boolean isVMField) { | |
411 java.lang.reflect.Field f = null; | |
412 try { | |
413 f = readField(field); | |
414 if (Modifier.isFinal(f.getModifiers())) return; | |
415 f.setAccessible(true); | |
416 f.setShort(obj, field.getValue(getObj())); | |
417 } catch (Exception ex) { | |
418 printFieldSetError(f, ex); | |
419 } | |
420 } | |
421 | |
422 public void doInt(IntField field, boolean isVMField) { | |
423 java.lang.reflect.Field f = null; | |
424 try { | |
425 f = readField(field); | |
426 if (Modifier.isFinal(f.getModifiers())) return; | |
427 f.setAccessible(true); | |
428 f.setInt(obj, field.getValue(getObj())); | |
429 } catch (Exception ex) { | |
430 printFieldSetError(f, ex); | |
431 } | |
432 } | |
433 | |
434 public void doLong(LongField field, boolean isVMField) { | |
435 java.lang.reflect.Field f = null; | |
436 try { | |
437 f = readField(field); | |
438 if (Modifier.isFinal(f.getModifiers())) return; | |
439 f.setAccessible(true); | |
440 f.setLong(obj, field.getValue(getObj())); | |
441 } catch (Exception ex) { | |
442 printFieldSetError(f, ex); | |
443 } | |
444 } | |
445 | |
446 public void doFloat(FloatField field, boolean isVMField) { | |
447 java.lang.reflect.Field f = null; | |
448 try { | |
449 f = readField(field); | |
450 if (Modifier.isFinal(f.getModifiers())) return; | |
451 f.setAccessible(true); | |
452 f.setFloat(obj, field.getValue(getObj())); | |
453 } catch (Exception ex) { | |
454 printFieldSetError(f, ex); | |
455 } | |
456 } | |
457 | |
458 public void doDouble(DoubleField field, boolean isVMField) { | |
459 java.lang.reflect.Field f = null; | |
460 try { | |
461 f = readField(field); | |
462 if (Modifier.isFinal(f.getModifiers())) return; | |
463 f.setAccessible(true); | |
464 f.setDouble(obj, field.getValue(getObj())); | |
465 } catch (Exception ex) { | |
466 printFieldSetError(f, ex); | |
467 } | |
468 } | |
469 | |
470 public void doCInt(CIntField field, boolean isVMField) { | |
471 throw new RuntimeException("should not reach here!"); | |
472 } | |
473 } | |
474 | |
475 public Class readClass(InstanceKlass kls) throws ClassNotFoundException { | |
476 Class cls = (Class) getFromObjTable(kls); | |
477 if (cls == null) { | |
478 cls = Class.forName(kls.getName().asString().replace('/', '.'), true, cl); | |
479 putIntoObjTable(kls, cls); | |
480 } | |
481 return cls; | |
482 } | |
483 | |
484 public Object readMethodOrConstructor(sun.jvm.hotspot.oops.Method m) | |
485 throws NoSuchMethodException, ClassNotFoundException { | |
486 String name = m.getName().asString(); | |
487 if (name.equals("<init>")) { | |
488 return readConstructor(m); | |
489 } else { | |
490 return readMethod(m); | |
491 } | |
492 } | |
493 | |
494 public java.lang.reflect.Method readMethod(sun.jvm.hotspot.oops.Method m) | |
495 throws NoSuchMethodException, ClassNotFoundException { | |
496 java.lang.reflect.Method result = (java.lang.reflect.Method) getFromObjTable(m); | |
497 if (result == null) { | |
498 Class clz = readClass((InstanceKlass)m.getMethodHolder()); | |
499 String name = m.getName().asString(); | |
500 Class[] paramTypes = getParamTypes(m.getSignature()); | |
501 result = clz.getMethod(name, paramTypes); | |
502 putIntoObjTable(m, result); | |
503 } | |
504 return result; | |
505 } | |
506 | |
507 public java.lang.reflect.Constructor readConstructor(sun.jvm.hotspot.oops.Method m) | |
508 throws NoSuchMethodException, ClassNotFoundException { | |
509 java.lang.reflect.Constructor result = (java.lang.reflect.Constructor) getFromObjTable(m); | |
510 if (result == null) { | |
511 Class clz = readClass((InstanceKlass)m.getMethodHolder()); | |
512 String name = m.getName().asString(); | |
513 Class[] paramTypes = getParamTypes(m.getSignature()); | |
514 result = clz.getDeclaredConstructor(paramTypes); | |
515 putIntoObjTable(m, result); | |
516 } | |
517 return result; | |
518 } | |
519 | |
520 public java.lang.reflect.Field readField(sun.jvm.hotspot.oops.Field f) | |
521 throws NoSuchFieldException, ClassNotFoundException { | |
522 java.lang.reflect.Field result = (java.lang.reflect.Field) fieldMap.get(f); | |
523 if (result == null) { | |
524 FieldIdentifier fieldId = f.getID(); | |
525 Class clz = readClass((InstanceKlass) f.getFieldHolder()); | |
526 String name = fieldId.getName(); | |
527 try { | |
528 result = clz.getField(name); | |
529 } catch (NoSuchFieldException nsfe) { | |
530 result = clz.getDeclaredField(name); | |
531 } | |
532 fieldMap.put(f, result); | |
533 } | |
534 return result; | |
535 } | |
536 | |
537 protected final ClassLoader cl; | |
538 protected Map oopToObjMap; // Map<Oop, Object> | |
539 protected Map fieldMap; // Map<sun.jvm.hotspot.oops.Field, java.lang.reflect.Field> | |
540 | |
541 protected void putIntoObjTable(Oop oop, Object obj) { | |
542 oopToObjMap.put(oop, obj); | |
543 } | |
544 | |
545 protected Object getFromObjTable(Oop oop) { | |
546 return oopToObjMap.get(oop); | |
547 } | |
548 | |
549 protected class SignatureParser extends SignatureIterator { | |
550 protected Vector tmp = new Vector(); // Vector<Class> | |
551 | |
552 public SignatureParser(Symbol s) { | |
553 super(s); | |
554 } | |
555 | |
556 public void doBool () { tmp.add(Boolean.TYPE); } | |
557 public void doChar () { tmp.add(Character.TYPE); } | |
558 public void doFloat () { tmp.add(Float.TYPE); } | |
559 public void doDouble() { tmp.add(Double.TYPE); } | |
560 public void doByte () { tmp.add(Byte.TYPE); } | |
561 public void doShort () { tmp.add(Short.TYPE); } | |
562 public void doInt () { tmp.add(Integer.TYPE); } | |
563 public void doLong () { tmp.add(Long.TYPE); } | |
564 public void doVoid () { | |
565 if(isReturnType()) { | |
566 tmp.add(Void.TYPE); | |
567 } else { | |
568 throw new RuntimeException("should not reach here"); | |
569 } | |
570 } | |
571 | |
572 public void doObject(int begin, int end) { | |
573 tmp.add(getClass(begin, end)); | |
574 } | |
575 | |
576 public void doArray (int begin, int end) { | |
577 int inner = arrayInnerBegin(begin); | |
578 Class elemCls = null; | |
579 switch (_signature.getByteAt(inner)) { | |
580 case 'B': elemCls = Boolean.TYPE; break; | |
581 case 'C': elemCls = Character.TYPE; break; | |
582 case 'D': elemCls = Double.TYPE; break; | |
583 case 'F': elemCls = Float.TYPE; break; | |
584 case 'I': elemCls = Integer.TYPE; break; | |
585 case 'J': elemCls = Long.TYPE; break; | |
586 case 'S': elemCls = Short.TYPE; break; | |
587 case 'Z': elemCls = Boolean.TYPE; break; | |
588 case 'L': elemCls = getClass(inner + 1, end); break; | |
589 default: break; | |
590 } | |
591 | |
592 int dimension = inner - begin; | |
593 // create 0 x 0 ... array and get class from that | |
594 int[] dimArray = new int[dimension]; | |
595 tmp.add(java.lang.reflect.Array.newInstance(elemCls, dimArray).getClass()); | |
596 } | |
597 | |
598 protected Class getClass(int begin, int end) { | |
599 String className = getClassName(begin, end); | |
600 try { | |
601 return Class.forName(className, true, cl); | |
602 } catch (Exception e) { | |
603 if (DEBUG) { | |
604 System.err.println("Can't load class " + className); | |
605 } | |
606 throw new RuntimeException(e); | |
607 } | |
608 } | |
609 | |
610 protected String getClassName(int begin, int end) { | |
611 StringBuffer buf = new StringBuffer(); | |
612 for (int i = begin; i < end; i++) { | |
613 char c = (char) (_signature.getByteAt(i) & 0xFF); | |
614 if (c == '/') { | |
615 buf.append('.'); | |
616 } else { | |
617 buf.append(c); | |
618 } | |
619 } | |
620 return buf.toString(); | |
621 } | |
622 | |
623 protected int arrayInnerBegin(int begin) { | |
624 while (_signature.getByteAt(begin) == '[') { | |
625 ++begin; | |
626 } | |
627 return begin; | |
628 } | |
629 | |
630 public int getNumParams() { | |
631 return tmp.size(); | |
632 } | |
633 | |
634 public Enumeration getParamTypes() { | |
635 return tmp.elements(); | |
636 } | |
637 } | |
638 | |
639 protected Class[] getParamTypes(Symbol signature) { | |
640 SignatureParser sp = new SignatureParser(signature); | |
641 sp.iterateParameters(); | |
642 Class result[] = new Class[sp.getNumParams()]; | |
643 Enumeration e = sp.getParamTypes(); | |
644 int i = 0; | |
645 while (e.hasMoreElements()) { | |
646 result[i] = (Class) e.nextElement(); | |
647 i++; | |
648 } | |
649 return result; | |
650 } | |
651 } |