0
|
1 /*
|
|
2 * Copyright 2002-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.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 }
|