Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/ObjectReader.java
41161 views
1
/*
2
* Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*
23
*/
24
25
package sun.jvm.hotspot.utilities;
26
27
import java.lang.reflect.Modifier;
28
import java.util.*;
29
import java.util.stream.*;
30
import sun.jvm.hotspot.debugger.*;
31
import sun.jvm.hotspot.oops.*;
32
import sun.jvm.hotspot.runtime.*;
33
import sun.jvm.hotspot.utilities.*;
34
35
/**
36
* ObjectReader can "deserialize" objects from debuggee.
37
*
38
* Class Loading:
39
*
40
* ObjectReader loads classes using the given class loader. If no
41
* class loader is supplied, it uses a ProcImageClassLoader, which
42
* loads classes from debuggee core or process.
43
44
* Object creation:
45
*
46
* This class uses no-arg constructor to construct objects. But if
47
* there is no no-arg constructor in a given class, then it tries to
48
* use other constructors with 'default' values - null for object
49
* types, 0, 0.0, false etc. for primitives. If this process fails to
50
* construct an instance (because of null checking by constructor or 0
51
* being invalid for an int arg etc.), then null is returned. While
52
* constructing complete object graph 'null' is inserted silently on
53
* failure and the deserialization continues to construct best-effort
54
* object graph.
55
*
56
* Debug messages:
57
*
58
* The flag sun.jvm.hotspot.utilities.ObjectReader.DEBUG may be set to
59
* non-null to get debug error messages and stack traces.
60
*
61
* JDK version:
62
*
63
* JDK classes are loaded by bootstrap class loader and not by the
64
* supplied class loader or ProcImageClassLoader. This may create
65
* problems if a JDK class evolves. i.e., if SA runs a JDK version
66
* different from that of the debuggee, there is a possibility of
67
* schema change. It is recommended that the matching JDK version be
68
* used to run SA for proper object deserialization.
69
*
70
*/
71
72
public class ObjectReader {
73
74
private static final boolean DEBUG;
75
static {
76
DEBUG = System.getProperty("sun.jvm.hotspot.utilities.ObjectReader.DEBUG") != null;
77
}
78
79
public ObjectReader(ClassLoader cl) {
80
this.cl = cl;
81
this.oopToObjMap = new HashMap<>();
82
this.fieldMap = new HashMap<>();
83
}
84
85
public ObjectReader() {
86
this(new ProcImageClassLoader());
87
}
88
89
static void debugPrintln(String msg) {
90
if (DEBUG) {
91
System.err.println("DEBUG>" + msg);
92
}
93
}
94
95
static void debugPrintStackTrace(Exception exp) {
96
if (DEBUG) {
97
StackTraceElement[] els = exp.getStackTrace();
98
for (int i = 0; i < els.length; i++) {
99
System.err.println("DEBUG>" + els[i].toString());
100
}
101
}
102
}
103
104
public Object readObject(Oop oop) throws ClassNotFoundException {
105
if (oop instanceof Instance) {
106
return readInstance((Instance) oop);
107
} else if (oop instanceof TypeArray){
108
return readPrimitiveArray((TypeArray)oop);
109
} else if (oop instanceof ObjArray){
110
return readObjectArray((ObjArray)oop);
111
} else {
112
return null;
113
}
114
}
115
116
protected final Object getDefaultPrimitiveValue(Class clz) {
117
if (clz == Boolean.TYPE) {
118
return Boolean.FALSE;
119
} else if (clz == Character.TYPE) {
120
return ' ';
121
} else if (clz == Byte.TYPE) {
122
return (byte) 0;
123
} else if (clz == Short.TYPE) {
124
return (short) 0;
125
} else if (clz == Integer.TYPE) {
126
return 0;
127
} else if (clz == Long.TYPE) {
128
return 0L;
129
} else if (clz == Float.TYPE) {
130
return 0.0f;
131
} else if (clz == Double.TYPE) {
132
return 0.0;
133
} else {
134
throw new RuntimeException("should not reach here!");
135
}
136
}
137
138
protected String javaLangString;
139
protected String javaUtilHashtableEntry;
140
protected String javaUtilHashtable;
141
protected String javaUtilProperties;
142
143
protected String javaLangString() {
144
if (javaLangString == null) {
145
javaLangString = "java/lang/String";
146
}
147
return javaLangString;
148
}
149
150
protected String javaUtilHashtableEntry() {
151
if (javaUtilHashtableEntry == null) {
152
javaUtilHashtableEntry = "java/util/Hashtable$Entry";
153
}
154
return javaUtilHashtableEntry;
155
}
156
157
protected String javaUtilHashtable() {
158
if (javaUtilHashtable == null) {
159
javaUtilHashtable = "java/util/Hashtable";
160
}
161
return javaUtilHashtable;
162
}
163
164
protected String javaUtilProperties() {
165
if (javaUtilProperties == null) {
166
javaUtilProperties = "java/util/Properties";
167
}
168
return javaUtilProperties;
169
}
170
171
private void setHashtableEntry(java.util.Hashtable<Object, Object> p, Oop oop) {
172
InstanceKlass ik = (InstanceKlass)oop.getKlass();
173
OopField keyField = (OopField)ik.findField("key", "Ljava/lang/Object;");
174
OopField valueField = (OopField)ik.findField("value", "Ljava/lang/Object;");
175
OopField nextField = (OopField)ik.findField("next", "Ljava/util/Hashtable$Entry;");
176
if (DEBUG) {
177
if (Assert.ASSERTS_ENABLED) {
178
Assert.that(ik.getName().equals(javaUtilHashtableEntry()), "Not a Hashtable$Entry?");
179
Assert.that(keyField != null && valueField != null && nextField != null, "Invalid fields!");
180
}
181
}
182
183
Object key = null;
184
Object value = null;
185
Oop next = null;
186
try {
187
key = readObject(keyField.getValue(oop));
188
value = readObject(valueField.getValue(oop));
189
next = (Oop)nextField.getValue(oop);
190
// For Properties, should use setProperty(k, v). Since it only runs in SA
191
// using put(k, v) should be OK.
192
p.put(key, value);
193
if (next != null) {
194
setHashtableEntry(p, next);
195
}
196
} catch (ClassNotFoundException ce) {
197
if( DEBUG) {
198
debugPrintln("Class not found " + ce);
199
debugPrintStackTrace(ce);
200
}
201
}
202
}
203
204
private void setPropertiesEntry(java.util.Properties p, Oop oop) {
205
InstanceKlass ik = (InstanceKlass)oop.getKlass();
206
OopField keyField = (OopField)ik.findField("key", "Ljava/lang/Object;");
207
OopField valueField = (OopField)ik.findField("val", "Ljava/lang/Object;");
208
OopField nextField = (OopField)ik.findField("next", "Ljava/util/concurrent/ConcurrentHashMap$Node;");
209
210
try {
211
p.setProperty((String)readObject(keyField.getValue(oop)),
212
(String)readObject(valueField.getValue(oop)));
213
} catch (ClassNotFoundException ce) {
214
if (DEBUG) {
215
debugPrintStackTrace(ce);
216
}
217
}
218
// If this hashmap table Node is chained, then follow the chain to the next Node.
219
Oop chainedOop = nextField.getValue(oop);
220
if (chainedOop != null) {
221
setPropertiesEntry(p, chainedOop);
222
}
223
}
224
225
protected Object getHashtable(Instance oop) {
226
InstanceKlass k = (InstanceKlass)oop.getKlass();
227
OopField tableField = (OopField)k.findField("table", "[Ljava/util/Hashtable$Entry;");
228
if (tableField == null) {
229
debugPrintln("Could not find field of [Ljava/util/Hashtable$Entry;");
230
return null;
231
}
232
java.util.Hashtable<Object, Object> table = new java.util.Hashtable<>();
233
ObjArray kvs = (ObjArray)tableField.getValue(oop);
234
long size = kvs.getLength();
235
debugPrintln("Hashtable$Entry Size = " + size);
236
for (long i=0; i<size; i++) {
237
Oop entry = kvs.getObjAt(i);
238
if (entry != null && entry.isInstance()) {
239
setHashtableEntry(table, entry);
240
}
241
}
242
return table;
243
}
244
245
private Properties getProperties(Instance oop) {
246
InstanceKlass k = (InstanceKlass)oop.getKlass();
247
OopField mapField = (OopField)k.findField("map", "Ljava/util/concurrent/ConcurrentHashMap;");
248
if (mapField == null) {
249
debugPrintln("Could not find field of Ljava/util/concurrent/ConcurrentHashMap");
250
return null;
251
}
252
253
Instance mapObj = (Instance)mapField.getValue(oop);
254
if (mapObj == null) {
255
debugPrintln("Could not get map field from java.util.Properties");
256
return null;
257
}
258
259
InstanceKlass mk = (InstanceKlass)mapObj.getKlass();
260
OopField tableField = (OopField)mk.findField("table", "[Ljava/util/concurrent/ConcurrentHashMap$Node;");
261
if (tableField == null) {
262
debugPrintln("Could not find field of [Ljava/util/concurrent/ConcurrentHashMap$Node");
263
return null;
264
}
265
266
java.util.Properties props = new java.util.Properties();
267
ObjArray kvs = (ObjArray)tableField.getValue(mapObj);
268
long size = kvs.getLength();
269
debugPrintln("ConcurrentHashMap$Node Size = " + size);
270
LongStream.range(0, size)
271
.mapToObj(kvs::getObjAt)
272
.filter(o -> o != null)
273
.forEach(o -> setPropertiesEntry(props, o));
274
275
return props;
276
}
277
278
public Object readInstance(Instance oop) throws ClassNotFoundException {
279
Object result = getFromObjTable(oop);
280
if (result == null) {
281
InstanceKlass kls = (InstanceKlass) oop.getKlass();
282
// Handle java.lang.String instances differently. As part of JSR-133, fields of immutable
283
// classes have been made final. The algorithm below will not be able to read Strings from
284
// debuggee (can't use reflection to set final fields). But, need to read Strings is very
285
// important.
286
// Same for Hashtable, key and hash are final, could not be set in the algorithm too.
287
// FIXME: need a framework to handle many other special cases.
288
if (kls.getName().equals(javaLangString())) {
289
return OopUtilities.stringOopToString(oop);
290
}
291
292
if (kls.getName().equals(javaUtilHashtable())) {
293
return getHashtable(oop);
294
}
295
296
if (kls.getName().equals(javaUtilProperties())) {
297
return getProperties(oop);
298
}
299
300
Class<?> clz = readClass(kls);
301
try {
302
result = clz.getDeclaredConstructor().newInstance();
303
} catch (Exception ex) {
304
// no-arg constructor failed to create object. Let us try
305
// to call constructors one-by-one with default arguments
306
// (null for objects, 0/0.0 etc. for primitives) till we
307
// succeed or fail on all constructors.
308
309
java.lang.reflect.Constructor[] ctrs = clz.getDeclaredConstructors();
310
for (int n = 0; n < ctrs.length; n++) {
311
java.lang.reflect.Constructor c = ctrs[n];
312
Class[] paramTypes = c.getParameterTypes();
313
Object[] params = new Object[paramTypes.length];
314
for (int i = 0; i < params.length; i++) {
315
if (paramTypes[i].isPrimitive()) {
316
params[i] = getDefaultPrimitiveValue(paramTypes[i]);
317
}
318
}
319
try {
320
c.setAccessible(true);
321
result = c.newInstance(params);
322
break;
323
} catch (Exception exp) {
324
if (DEBUG) {
325
debugPrintln("Can't create object using " + c);
326
debugPrintStackTrace(exp);
327
}
328
}
329
}
330
}
331
332
if (result != null) {
333
putIntoObjTable(oop, result);
334
oop.iterate(new FieldSetter(result), false);
335
}
336
}
337
return result;
338
}
339
340
public Object readPrimitiveArray(final TypeArray array) {
341
342
Object result = getFromObjTable(array);
343
if (result == null) {
344
int length = (int) array.getLength();
345
TypeArrayKlass klass = (TypeArrayKlass) array.getKlass();
346
int type = (int) klass.getElementType();
347
switch (type) {
348
case TypeArrayKlass.T_BOOLEAN: {
349
final boolean[] arrayObj = new boolean[length];
350
array.iterate(new DefaultOopVisitor() {
351
public void doBoolean(BooleanField field, boolean isVMField) {
352
IndexableFieldIdentifier ifd = (IndexableFieldIdentifier) field.getID();
353
arrayObj[ifd.getIndex()] = field.getValue(array);
354
}
355
}, false);
356
result = arrayObj;
357
}
358
break;
359
360
case TypeArrayKlass.T_CHAR: {
361
final char[] arrayObj = new char[length];
362
array.iterate(new DefaultOopVisitor() {
363
public void doChar(CharField field, boolean isVMField) {
364
IndexableFieldIdentifier ifd = (IndexableFieldIdentifier) field.getID();
365
arrayObj[ifd.getIndex()] = field.getValue(array);
366
}
367
}, false);
368
result = arrayObj;
369
}
370
break;
371
372
case TypeArrayKlass.T_FLOAT: {
373
final float[] arrayObj = new float[length];
374
array.iterate(new DefaultOopVisitor() {
375
public void doFloat(FloatField field, boolean isVMField) {
376
IndexableFieldIdentifier ifd = (IndexableFieldIdentifier) field.getID();
377
arrayObj[ifd.getIndex()] = field.getValue(array);
378
}
379
}, false);
380
result = arrayObj;
381
}
382
break;
383
384
case TypeArrayKlass.T_DOUBLE: {
385
final double[] arrayObj = new double[length];
386
array.iterate(new DefaultOopVisitor() {
387
public void doDouble(DoubleField field, boolean isVMField) {
388
IndexableFieldIdentifier ifd = (IndexableFieldIdentifier) field.getID();
389
arrayObj[ifd.getIndex()] = field.getValue(array);
390
}
391
}, false);
392
result = arrayObj;
393
}
394
break;
395
396
case TypeArrayKlass.T_BYTE: {
397
final byte[] arrayObj = new byte[length];
398
array.iterate(new DefaultOopVisitor() {
399
public void doByte(ByteField field, boolean isVMField) {
400
IndexableFieldIdentifier ifd = (IndexableFieldIdentifier) field.getID();
401
arrayObj[ifd.getIndex()] = field.getValue(array);
402
}
403
}, false);
404
result = arrayObj;
405
}
406
break;
407
408
case TypeArrayKlass.T_SHORT: {
409
final short[] arrayObj = new short[length];
410
array.iterate(new DefaultOopVisitor() {
411
public void doShort(ShortField field, boolean isVMField) {
412
IndexableFieldIdentifier ifd = (IndexableFieldIdentifier) field.getID();
413
arrayObj[ifd.getIndex()] = field.getValue(array);
414
}
415
}, false);
416
result = arrayObj;
417
}
418
break;
419
420
case TypeArrayKlass.T_INT: {
421
final int[] arrayObj = new int[length];
422
array.iterate(new DefaultOopVisitor() {
423
public void doInt(IntField field, boolean isVMField) {
424
IndexableFieldIdentifier ifd = (IndexableFieldIdentifier) field.getID();
425
arrayObj[ifd.getIndex()] = field.getValue(array);
426
}
427
}, false);
428
result = arrayObj;
429
}
430
break;
431
432
case TypeArrayKlass.T_LONG: {
433
final long[] arrayObj = new long[length];
434
array.iterate(new DefaultOopVisitor() {
435
public void doLong(LongField field, boolean isVMField) {
436
IndexableFieldIdentifier ifd = (IndexableFieldIdentifier) field.getID();
437
arrayObj[ifd.getIndex()] = field.getValue(array);
438
}
439
}, false);
440
result = arrayObj;
441
}
442
break;
443
444
default:
445
throw new RuntimeException("should not reach here!");
446
}
447
448
putIntoObjTable(array, result);
449
}
450
return result;
451
}
452
453
protected final boolean isRobust(OopHandle handle) {
454
return RobustOopDeterminator.oopLooksValid(handle);
455
}
456
457
public Object readObjectArray(final ObjArray array) throws ClassNotFoundException {
458
Object result = getFromObjTable(array);
459
if (result == null) {
460
int length = (int) array.getLength();
461
ObjArrayKlass klass = (ObjArrayKlass) array.getKlass();
462
Klass bottomKls = klass.getBottomKlass();
463
Class bottomCls = null;
464
final int dimension = (int) klass.getDimension();
465
int[] dimArray = null;
466
if (bottomKls instanceof InstanceKlass) {
467
bottomCls = readClass((InstanceKlass) bottomKls);
468
dimArray = new int[dimension];
469
} else { // instanceof TypeArrayKlass
470
TypeArrayKlass botKls = (TypeArrayKlass) bottomKls;
471
dimArray = new int[dimension -1];
472
}
473
// initialize the length
474
dimArray[0] = length;
475
final Object[] arrayObj = (Object[]) java.lang.reflect.Array.newInstance(bottomCls, dimArray);
476
putIntoObjTable(array, arrayObj);
477
result = arrayObj;
478
array.iterate(new DefaultOopVisitor() {
479
public void doOop(OopField field, boolean isVMField) {
480
OopHandle handle = field.getValueAsOopHandle(getObj());
481
if (! isRobust(handle)) {
482
return;
483
}
484
485
IndexableFieldIdentifier ifd = (IndexableFieldIdentifier) field.getID();
486
try {
487
arrayObj[ifd.getIndex()] = readObject(field.getValue(getObj()));
488
} catch (Exception e) {
489
if (DEBUG) {
490
debugPrintln("Array element set failed for " + ifd);
491
debugPrintStackTrace(e);
492
}
493
}
494
}
495
}, false);
496
}
497
return result;
498
}
499
500
protected class FieldSetter extends DefaultOopVisitor {
501
protected Object obj;
502
503
public FieldSetter(Object obj) {
504
this.obj = obj;
505
}
506
507
private void printFieldSetError(java.lang.reflect.Field f, Exception ex) {
508
if (DEBUG) {
509
if (f != null) debugPrintln("Field set failed for " + f);
510
debugPrintStackTrace(ex);
511
}
512
}
513
514
// Callback methods for each field type in an object
515
public void doOop(OopField field, boolean isVMField) {
516
OopHandle handle = field.getValueAsOopHandle(getObj());
517
if (! isRobust(handle) ) {
518
return;
519
}
520
521
java.lang.reflect.Field f = null;
522
try {
523
f = readField(field);
524
if (Modifier.isFinal(f.getModifiers())) return;
525
f.setAccessible(true);
526
f.set(obj, readObject(field.getValue(getObj())));
527
} catch (Exception ex) {
528
printFieldSetError(f, ex);
529
}
530
}
531
532
public void doByte(ByteField field, boolean isVMField) {
533
java.lang.reflect.Field f = null;
534
try {
535
f = readField(field);
536
if (Modifier.isFinal(f.getModifiers())) return;
537
f.setAccessible(true);
538
f.setByte(obj, field.getValue(getObj()));
539
} catch (Exception ex) {
540
printFieldSetError(f, ex);
541
}
542
}
543
544
public void doChar(CharField field, boolean isVMField) {
545
java.lang.reflect.Field f = null;
546
try {
547
f = readField(field);
548
if (Modifier.isFinal(f.getModifiers())) return;
549
f.setAccessible(true);
550
f.setChar(obj, field.getValue(getObj()));
551
} catch (Exception ex) {
552
printFieldSetError(f, ex);
553
}
554
}
555
556
public void doBoolean(BooleanField field, boolean isVMField) {
557
java.lang.reflect.Field f = null;
558
try {
559
f = readField(field);
560
if (Modifier.isFinal(f.getModifiers())) return;
561
f.setAccessible(true);
562
f.setBoolean(obj, field.getValue(getObj()));
563
} catch (Exception ex) {
564
printFieldSetError(f, ex);
565
}
566
}
567
568
public void doShort(ShortField field, boolean isVMField) {
569
java.lang.reflect.Field f = null;
570
try {
571
f = readField(field);
572
if (Modifier.isFinal(f.getModifiers())) return;
573
f.setAccessible(true);
574
f.setShort(obj, field.getValue(getObj()));
575
} catch (Exception ex) {
576
printFieldSetError(f, ex);
577
}
578
}
579
580
public void doInt(IntField field, boolean isVMField) {
581
java.lang.reflect.Field f = null;
582
try {
583
f = readField(field);
584
if (Modifier.isFinal(f.getModifiers())) return;
585
f.setAccessible(true);
586
f.setInt(obj, field.getValue(getObj()));
587
} catch (Exception ex) {
588
printFieldSetError(f, ex);
589
}
590
}
591
592
public void doLong(LongField field, boolean isVMField) {
593
java.lang.reflect.Field f = null;
594
try {
595
f = readField(field);
596
if (Modifier.isFinal(f.getModifiers())) return;
597
f.setAccessible(true);
598
f.setLong(obj, field.getValue(getObj()));
599
} catch (Exception ex) {
600
printFieldSetError(f, ex);
601
}
602
}
603
604
public void doFloat(FloatField field, boolean isVMField) {
605
java.lang.reflect.Field f = null;
606
try {
607
f = readField(field);
608
if (Modifier.isFinal(f.getModifiers())) return;
609
f.setAccessible(true);
610
f.setFloat(obj, field.getValue(getObj()));
611
} catch (Exception ex) {
612
printFieldSetError(f, ex);
613
}
614
}
615
616
public void doDouble(DoubleField field, boolean isVMField) {
617
java.lang.reflect.Field f = null;
618
try {
619
f = readField(field);
620
if (Modifier.isFinal(f.getModifiers())) return;
621
f.setAccessible(true);
622
f.setDouble(obj, field.getValue(getObj()));
623
} catch (Exception ex) {
624
printFieldSetError(f, ex);
625
}
626
}
627
628
public void doCInt(CIntField field, boolean isVMField) {
629
throw new RuntimeException("should not reach here!");
630
}
631
}
632
633
public Class readClass(InstanceKlass kls) throws ClassNotFoundException {
634
Class cls = (Class) getFromObjTable(kls);
635
if (cls == null) {
636
cls = Class.forName(kls.getName().asString().replace('/', '.'), true, cl);
637
putIntoObjTable(kls, cls);
638
}
639
return cls;
640
}
641
642
public Object readMethodOrConstructor(sun.jvm.hotspot.oops.Method m)
643
throws NoSuchMethodException, ClassNotFoundException {
644
String name = m.getName().asString();
645
if (name.equals("<init>")) {
646
return readConstructor(m);
647
} else {
648
return readMethod(m);
649
}
650
}
651
652
public java.lang.reflect.Method readMethod(sun.jvm.hotspot.oops.Method m)
653
throws NoSuchMethodException, ClassNotFoundException {
654
java.lang.reflect.Method result = (java.lang.reflect.Method) getFromObjTable(m);
655
if (result == null) {
656
Class<?> clz = readClass(m.getMethodHolder());
657
String name = m.getName().asString();
658
Class[] paramTypes = getParamTypes(m.getSignature());
659
result = clz.getMethod(name, paramTypes);
660
putIntoObjTable(m, result);
661
}
662
return result;
663
}
664
665
public java.lang.reflect.Constructor readConstructor(sun.jvm.hotspot.oops.Method m)
666
throws NoSuchMethodException, ClassNotFoundException {
667
java.lang.reflect.Constructor result = (java.lang.reflect.Constructor) getFromObjTable(m);
668
if (result == null) {
669
Class<?> clz = readClass(m.getMethodHolder());
670
String name = m.getName().asString();
671
Class[] paramTypes = getParamTypes(m.getSignature());
672
result = clz.getDeclaredConstructor(paramTypes);
673
putIntoObjTable(m, result);
674
}
675
return result;
676
}
677
678
public java.lang.reflect.Field readField(sun.jvm.hotspot.oops.Field f)
679
throws NoSuchFieldException, ClassNotFoundException {
680
java.lang.reflect.Field result = (java.lang.reflect.Field) fieldMap.get(f);
681
if (result == null) {
682
FieldIdentifier fieldId = f.getID();
683
Class clz = readClass((InstanceKlass) f.getFieldHolder());
684
String name = fieldId.getName();
685
try {
686
result = clz.getField(name);
687
} catch (NoSuchFieldException nsfe) {
688
result = clz.getDeclaredField(name);
689
}
690
fieldMap.put(f, result);
691
}
692
return result;
693
}
694
695
protected final ClassLoader cl;
696
protected Map<Object, Object> oopToObjMap;
697
protected Map<sun.jvm.hotspot.oops.Field, java.lang.reflect.Field> fieldMap;
698
699
protected void putIntoObjTable(Oop oop, Object obj) {
700
oopToObjMap.put(oop, obj);
701
}
702
703
protected Object getFromObjTable(Oop oop) {
704
return oopToObjMap.get(oop);
705
}
706
707
protected void putIntoObjTable(Metadata oop, Object obj) {
708
oopToObjMap.put(oop, obj);
709
}
710
711
protected Object getFromObjTable(Metadata oop) {
712
return oopToObjMap.get(oop);
713
}
714
715
protected class SignatureParser extends SignatureIterator {
716
protected Vector<Class<?>> tmp = new Vector<>();
717
718
public SignatureParser(Symbol s) {
719
super(s);
720
}
721
722
public void doBool () { tmp.add(Boolean.TYPE); }
723
public void doChar () { tmp.add(Character.TYPE); }
724
public void doFloat () { tmp.add(Float.TYPE); }
725
public void doDouble() { tmp.add(Double.TYPE); }
726
public void doByte () { tmp.add(Byte.TYPE); }
727
public void doShort () { tmp.add(Short.TYPE); }
728
public void doInt () { tmp.add(Integer.TYPE); }
729
public void doLong () { tmp.add(Long.TYPE); }
730
public void doVoid () {
731
if(isReturnType()) {
732
tmp.add(Void.TYPE);
733
} else {
734
throw new RuntimeException("should not reach here");
735
}
736
}
737
738
public void doObject(int begin, int end) {
739
tmp.add(getClass(begin, end));
740
}
741
742
public void doArray (int begin, int end) {
743
int inner = arrayInnerBegin(begin);
744
Class elemCls = null;
745
switch (_signature.getByteAt(inner)) {
746
case 'B': elemCls = Boolean.TYPE; break;
747
case 'C': elemCls = Character.TYPE; break;
748
case 'D': elemCls = Double.TYPE; break;
749
case 'F': elemCls = Float.TYPE; break;
750
case 'I': elemCls = Integer.TYPE; break;
751
case 'J': elemCls = Long.TYPE; break;
752
case 'S': elemCls = Short.TYPE; break;
753
case 'Z': elemCls = Boolean.TYPE; break;
754
case 'L': elemCls = getClass(inner + 1, end); break;
755
default: break;
756
}
757
758
int dimension = inner - begin;
759
// create 0 x 0 ... array and get class from that
760
int[] dimArray = new int[dimension];
761
tmp.add(java.lang.reflect.Array.newInstance(elemCls, dimArray).getClass());
762
}
763
764
protected Class getClass(int begin, int end) {
765
String className = getClassName(begin, end);
766
try {
767
return Class.forName(className, true, cl);
768
} catch (Exception e) {
769
if (DEBUG) {
770
debugPrintln("Can't load class " + className);
771
}
772
throw new RuntimeException(e);
773
}
774
}
775
776
protected String getClassName(int begin, int end) {
777
StringBuilder buf = new StringBuilder();
778
for (int i = begin; i < end; i++) {
779
char c = (char) (_signature.getByteAt(i) & 0xFF);
780
if (c == '/') {
781
buf.append('.');
782
} else {
783
buf.append(c);
784
}
785
}
786
return buf.toString();
787
}
788
789
protected int arrayInnerBegin(int begin) {
790
while (_signature.getByteAt(begin) == '[') {
791
++begin;
792
}
793
return begin;
794
}
795
796
public int getNumParams() {
797
return tmp.size();
798
}
799
800
public Enumeration getParamTypes() {
801
return tmp.elements();
802
}
803
}
804
805
protected Class[] getParamTypes(Symbol signature) {
806
SignatureParser sp = new SignatureParser(signature);
807
sp.iterateParameters();
808
Class result[] = new Class[sp.getNumParams()];
809
Enumeration e = sp.getParamTypes();
810
int i = 0;
811
while (e.hasMoreElements()) {
812
result[i] = (Class) e.nextElement();
813
i++;
814
}
815
return result;
816
}
817
}
818
819