Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/reflect/MethodAccessorGenerator.java
38829 views
1
/*
2
* Copyright (c) 2001, 2013, 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. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package sun.reflect;
27
28
import java.security.AccessController;
29
import java.security.PrivilegedAction;
30
31
/** Generator for sun.reflect.MethodAccessor and
32
sun.reflect.ConstructorAccessor objects using bytecodes to
33
implement reflection. A java.lang.reflect.Method or
34
java.lang.reflect.Constructor object can delegate its invoke or
35
newInstance method to an accessor using native code or to one
36
generated by this class. (Methods and Constructors were merged
37
together in this class to ensure maximum code sharing.) */
38
39
class MethodAccessorGenerator extends AccessorGenerator {
40
41
private static final short NUM_BASE_CPOOL_ENTRIES = (short) 12;
42
// One for invoke() plus one for constructor
43
private static final short NUM_METHODS = (short) 2;
44
// Only used if forSerialization is true
45
private static final short NUM_SERIALIZATION_CPOOL_ENTRIES = (short) 2;
46
47
private static volatile int methodSymnum = 0;
48
private static volatile int constructorSymnum = 0;
49
private static volatile int serializationConstructorSymnum = 0;
50
51
private Class<?> declaringClass;
52
private Class<?>[] parameterTypes;
53
private Class<?> returnType;
54
private boolean isConstructor;
55
private boolean forSerialization;
56
57
private short targetMethodRef;
58
private short invokeIdx;
59
private short invokeDescriptorIdx;
60
// Constant pool index of CONSTANT_Class_info for first
61
// non-primitive parameter type. Should be incremented by 2.
62
private short nonPrimitiveParametersBaseIdx;
63
64
MethodAccessorGenerator() {
65
}
66
67
/** This routine is not thread-safe */
68
public MethodAccessor generateMethod(Class<?> declaringClass,
69
String name,
70
Class<?>[] parameterTypes,
71
Class<?> returnType,
72
Class<?>[] checkedExceptions,
73
int modifiers)
74
{
75
return (MethodAccessor) generate(declaringClass,
76
name,
77
parameterTypes,
78
returnType,
79
checkedExceptions,
80
modifiers,
81
false,
82
false,
83
null);
84
}
85
86
/** This routine is not thread-safe */
87
public ConstructorAccessor generateConstructor(Class<?> declaringClass,
88
Class<?>[] parameterTypes,
89
Class<?>[] checkedExceptions,
90
int modifiers)
91
{
92
return (ConstructorAccessor) generate(declaringClass,
93
"<init>",
94
parameterTypes,
95
Void.TYPE,
96
checkedExceptions,
97
modifiers,
98
true,
99
false,
100
null);
101
}
102
103
/** This routine is not thread-safe */
104
public SerializationConstructorAccessorImpl
105
generateSerializationConstructor(Class<?> declaringClass,
106
Class<?>[] parameterTypes,
107
Class<?>[] checkedExceptions,
108
int modifiers,
109
Class<?> targetConstructorClass)
110
{
111
return (SerializationConstructorAccessorImpl)
112
generate(declaringClass,
113
"<init>",
114
parameterTypes,
115
Void.TYPE,
116
checkedExceptions,
117
modifiers,
118
true,
119
true,
120
targetConstructorClass);
121
}
122
123
/** This routine is not thread-safe */
124
private MagicAccessorImpl generate(final Class<?> declaringClass,
125
String name,
126
Class<?>[] parameterTypes,
127
Class<?> returnType,
128
Class<?>[] checkedExceptions,
129
int modifiers,
130
boolean isConstructor,
131
boolean forSerialization,
132
Class<?> serializationTargetClass)
133
{
134
ByteVector vec = ByteVectorFactory.create();
135
asm = new ClassFileAssembler(vec);
136
this.declaringClass = declaringClass;
137
this.parameterTypes = parameterTypes;
138
this.returnType = returnType;
139
this.modifiers = modifiers;
140
this.isConstructor = isConstructor;
141
this.forSerialization = forSerialization;
142
143
asm.emitMagicAndVersion();
144
145
// Constant pool entries:
146
// ( * = Boxing information: optional)
147
// (+ = Shared entries provided by AccessorGenerator)
148
// (^ = Only present if generating SerializationConstructorAccessor)
149
// [UTF-8] [This class's name]
150
// [CONSTANT_Class_info] for above
151
// [UTF-8] "sun/reflect/{MethodAccessorImpl,ConstructorAccessorImpl,SerializationConstructorAccessorImpl}"
152
// [CONSTANT_Class_info] for above
153
// [UTF-8] [Target class's name]
154
// [CONSTANT_Class_info] for above
155
// ^ [UTF-8] [Serialization: Class's name in which to invoke constructor]
156
// ^ [CONSTANT_Class_info] for above
157
// [UTF-8] target method or constructor name
158
// [UTF-8] target method or constructor signature
159
// [CONSTANT_NameAndType_info] for above
160
// [CONSTANT_Methodref_info or CONSTANT_InterfaceMethodref_info] for target method
161
// [UTF-8] "invoke" or "newInstance"
162
// [UTF-8] invoke or newInstance descriptor
163
// [UTF-8] descriptor for type of non-primitive parameter 1
164
// [CONSTANT_Class_info] for type of non-primitive parameter 1
165
// ...
166
// [UTF-8] descriptor for type of non-primitive parameter n
167
// [CONSTANT_Class_info] for type of non-primitive parameter n
168
// + [UTF-8] "java/lang/Exception"
169
// + [CONSTANT_Class_info] for above
170
// + [UTF-8] "java/lang/ClassCastException"
171
// + [CONSTANT_Class_info] for above
172
// + [UTF-8] "java/lang/NullPointerException"
173
// + [CONSTANT_Class_info] for above
174
// + [UTF-8] "java/lang/IllegalArgumentException"
175
// + [CONSTANT_Class_info] for above
176
// + [UTF-8] "java/lang/InvocationTargetException"
177
// + [CONSTANT_Class_info] for above
178
// + [UTF-8] "<init>"
179
// + [UTF-8] "()V"
180
// + [CONSTANT_NameAndType_info] for above
181
// + [CONSTANT_Methodref_info] for NullPointerException's constructor
182
// + [CONSTANT_Methodref_info] for IllegalArgumentException's constructor
183
// + [UTF-8] "(Ljava/lang/String;)V"
184
// + [CONSTANT_NameAndType_info] for "<init>(Ljava/lang/String;)V"
185
// + [CONSTANT_Methodref_info] for IllegalArgumentException's constructor taking a String
186
// + [UTF-8] "(Ljava/lang/Throwable;)V"
187
// + [CONSTANT_NameAndType_info] for "<init>(Ljava/lang/Throwable;)V"
188
// + [CONSTANT_Methodref_info] for InvocationTargetException's constructor
189
// + [CONSTANT_Methodref_info] for "super()"
190
// + [UTF-8] "java/lang/Object"
191
// + [CONSTANT_Class_info] for above
192
// + [UTF-8] "toString"
193
// + [UTF-8] "()Ljava/lang/String;"
194
// + [CONSTANT_NameAndType_info] for "toString()Ljava/lang/String;"
195
// + [CONSTANT_Methodref_info] for Object's toString method
196
// + [UTF-8] "Code"
197
// + [UTF-8] "Exceptions"
198
// * [UTF-8] "java/lang/Boolean"
199
// * [CONSTANT_Class_info] for above
200
// * [UTF-8] "(Z)V"
201
// * [CONSTANT_NameAndType_info] for above
202
// * [CONSTANT_Methodref_info] for above
203
// * [UTF-8] "booleanValue"
204
// * [UTF-8] "()Z"
205
// * [CONSTANT_NameAndType_info] for above
206
// * [CONSTANT_Methodref_info] for above
207
// * [UTF-8] "java/lang/Byte"
208
// * [CONSTANT_Class_info] for above
209
// * [UTF-8] "(B)V"
210
// * [CONSTANT_NameAndType_info] for above
211
// * [CONSTANT_Methodref_info] for above
212
// * [UTF-8] "byteValue"
213
// * [UTF-8] "()B"
214
// * [CONSTANT_NameAndType_info] for above
215
// * [CONSTANT_Methodref_info] for above
216
// * [UTF-8] "java/lang/Character"
217
// * [CONSTANT_Class_info] for above
218
// * [UTF-8] "(C)V"
219
// * [CONSTANT_NameAndType_info] for above
220
// * [CONSTANT_Methodref_info] for above
221
// * [UTF-8] "charValue"
222
// * [UTF-8] "()C"
223
// * [CONSTANT_NameAndType_info] for above
224
// * [CONSTANT_Methodref_info] for above
225
// * [UTF-8] "java/lang/Double"
226
// * [CONSTANT_Class_info] for above
227
// * [UTF-8] "(D)V"
228
// * [CONSTANT_NameAndType_info] for above
229
// * [CONSTANT_Methodref_info] for above
230
// * [UTF-8] "doubleValue"
231
// * [UTF-8] "()D"
232
// * [CONSTANT_NameAndType_info] for above
233
// * [CONSTANT_Methodref_info] for above
234
// * [UTF-8] "java/lang/Float"
235
// * [CONSTANT_Class_info] for above
236
// * [UTF-8] "(F)V"
237
// * [CONSTANT_NameAndType_info] for above
238
// * [CONSTANT_Methodref_info] for above
239
// * [UTF-8] "floatValue"
240
// * [UTF-8] "()F"
241
// * [CONSTANT_NameAndType_info] for above
242
// * [CONSTANT_Methodref_info] for above
243
// * [UTF-8] "java/lang/Integer"
244
// * [CONSTANT_Class_info] for above
245
// * [UTF-8] "(I)V"
246
// * [CONSTANT_NameAndType_info] for above
247
// * [CONSTANT_Methodref_info] for above
248
// * [UTF-8] "intValue"
249
// * [UTF-8] "()I"
250
// * [CONSTANT_NameAndType_info] for above
251
// * [CONSTANT_Methodref_info] for above
252
// * [UTF-8] "java/lang/Long"
253
// * [CONSTANT_Class_info] for above
254
// * [UTF-8] "(J)V"
255
// * [CONSTANT_NameAndType_info] for above
256
// * [CONSTANT_Methodref_info] for above
257
// * [UTF-8] "longValue"
258
// * [UTF-8] "()J"
259
// * [CONSTANT_NameAndType_info] for above
260
// * [CONSTANT_Methodref_info] for above
261
// * [UTF-8] "java/lang/Short"
262
// * [CONSTANT_Class_info] for above
263
// * [UTF-8] "(S)V"
264
// * [CONSTANT_NameAndType_info] for above
265
// * [CONSTANT_Methodref_info] for above
266
// * [UTF-8] "shortValue"
267
// * [UTF-8] "()S"
268
// * [CONSTANT_NameAndType_info] for above
269
// * [CONSTANT_Methodref_info] for above
270
271
short numCPEntries = NUM_BASE_CPOOL_ENTRIES + NUM_COMMON_CPOOL_ENTRIES;
272
boolean usesPrimitives = usesPrimitiveTypes();
273
if (usesPrimitives) {
274
numCPEntries += NUM_BOXING_CPOOL_ENTRIES;
275
}
276
if (forSerialization) {
277
numCPEntries += NUM_SERIALIZATION_CPOOL_ENTRIES;
278
}
279
280
// Add in variable-length number of entries to be able to describe
281
// non-primitive parameter types and checked exceptions.
282
numCPEntries += (short) (2 * numNonPrimitiveParameterTypes());
283
284
asm.emitShort(add(numCPEntries, S1));
285
286
final String generatedName = generateName(isConstructor, forSerialization);
287
asm.emitConstantPoolUTF8(generatedName);
288
asm.emitConstantPoolClass(asm.cpi());
289
thisClass = asm.cpi();
290
if (isConstructor) {
291
if (forSerialization) {
292
asm.emitConstantPoolUTF8
293
("sun/reflect/SerializationConstructorAccessorImpl");
294
} else {
295
asm.emitConstantPoolUTF8("sun/reflect/ConstructorAccessorImpl");
296
}
297
} else {
298
asm.emitConstantPoolUTF8("sun/reflect/MethodAccessorImpl");
299
}
300
asm.emitConstantPoolClass(asm.cpi());
301
superClass = asm.cpi();
302
asm.emitConstantPoolUTF8(getClassName(declaringClass, false));
303
asm.emitConstantPoolClass(asm.cpi());
304
targetClass = asm.cpi();
305
short serializationTargetClassIdx = (short) 0;
306
if (forSerialization) {
307
asm.emitConstantPoolUTF8(getClassName(serializationTargetClass, false));
308
asm.emitConstantPoolClass(asm.cpi());
309
serializationTargetClassIdx = asm.cpi();
310
}
311
asm.emitConstantPoolUTF8(name);
312
asm.emitConstantPoolUTF8(buildInternalSignature());
313
asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());
314
if (isInterface()) {
315
asm.emitConstantPoolInterfaceMethodref(targetClass, asm.cpi());
316
} else {
317
if (forSerialization) {
318
asm.emitConstantPoolMethodref(serializationTargetClassIdx, asm.cpi());
319
} else {
320
asm.emitConstantPoolMethodref(targetClass, asm.cpi());
321
}
322
}
323
targetMethodRef = asm.cpi();
324
if (isConstructor) {
325
asm.emitConstantPoolUTF8("newInstance");
326
} else {
327
asm.emitConstantPoolUTF8("invoke");
328
}
329
invokeIdx = asm.cpi();
330
if (isConstructor) {
331
asm.emitConstantPoolUTF8("([Ljava/lang/Object;)Ljava/lang/Object;");
332
} else {
333
asm.emitConstantPoolUTF8
334
("(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;");
335
}
336
invokeDescriptorIdx = asm.cpi();
337
338
// Output class information for non-primitive parameter types
339
nonPrimitiveParametersBaseIdx = add(asm.cpi(), S2);
340
for (int i = 0; i < parameterTypes.length; i++) {
341
Class<?> c = parameterTypes[i];
342
if (!isPrimitive(c)) {
343
asm.emitConstantPoolUTF8(getClassName(c, false));
344
asm.emitConstantPoolClass(asm.cpi());
345
}
346
}
347
348
// Entries common to FieldAccessor, MethodAccessor and ConstructorAccessor
349
emitCommonConstantPoolEntries();
350
351
// Boxing entries
352
if (usesPrimitives) {
353
emitBoxingContantPoolEntries();
354
}
355
356
if (asm.cpi() != numCPEntries) {
357
throw new InternalError("Adjust this code (cpi = " + asm.cpi() +
358
", numCPEntries = " + numCPEntries + ")");
359
}
360
361
// Access flags
362
asm.emitShort(ACC_PUBLIC);
363
364
// This class
365
asm.emitShort(thisClass);
366
367
// Superclass
368
asm.emitShort(superClass);
369
370
// Interfaces count and interfaces
371
asm.emitShort(S0);
372
373
// Fields count and fields
374
asm.emitShort(S0);
375
376
// Methods count and methods
377
asm.emitShort(NUM_METHODS);
378
379
emitConstructor();
380
emitInvoke();
381
382
// Additional attributes (none)
383
asm.emitShort(S0);
384
385
// Load class
386
vec.trim();
387
final byte[] bytes = vec.getData();
388
// Note: the class loader is the only thing that really matters
389
// here -- it's important to get the generated code into the
390
// same namespace as the target class. Since the generated code
391
// is privileged anyway, the protection domain probably doesn't
392
// matter.
393
return AccessController.doPrivileged(
394
new PrivilegedAction<MagicAccessorImpl>() {
395
public MagicAccessorImpl run() {
396
try {
397
return (MagicAccessorImpl)
398
ClassDefiner.defineClass
399
(generatedName,
400
bytes,
401
0,
402
bytes.length,
403
declaringClass.getClassLoader()).newInstance();
404
} catch (InstantiationException | IllegalAccessException e) {
405
throw new InternalError(e);
406
}
407
}
408
});
409
}
410
411
/** This emits the code for either invoke() or newInstance() */
412
private void emitInvoke() {
413
// NOTE that this code will only handle 65535 parameters since we
414
// use the sipush instruction to get the array index on the
415
// operand stack.
416
if (parameterTypes.length > 65535) {
417
throw new InternalError("Can't handle more than 65535 parameters");
418
}
419
420
// Generate code into fresh code buffer
421
ClassFileAssembler cb = new ClassFileAssembler();
422
if (isConstructor) {
423
// 1 incoming argument
424
cb.setMaxLocals(2);
425
} else {
426
// 2 incoming arguments
427
cb.setMaxLocals(3);
428
}
429
430
short illegalArgStartPC = 0;
431
432
if (isConstructor) {
433
// Instantiate target class before continuing
434
// new <target class type>
435
// dup
436
cb.opc_new(targetClass);
437
cb.opc_dup();
438
} else {
439
// Setup before iterating down argument list
440
if (isPrimitive(returnType)) {
441
// new <boxing type for primitive type>
442
// dup
443
// ... (see below:)
444
// invokespecial <constructor for boxing type for primitive type>
445
// areturn
446
cb.opc_new(indexForPrimitiveType(returnType));
447
cb.opc_dup();
448
}
449
450
// Get target object on operand stack if necessary.
451
452
// We need to do an explicit null check here; we won't see
453
// NullPointerExceptions from the invoke bytecode, since it's
454
// covered by an exception handler.
455
if (!isStatic()) {
456
// aload_1
457
// ifnonnull <checkcast label>
458
// new <NullPointerException>
459
// dup
460
// invokespecial <NullPointerException ctor>
461
// athrow
462
// <checkcast label:>
463
// aload_1
464
// checkcast <target class's type>
465
cb.opc_aload_1();
466
Label l = new Label();
467
cb.opc_ifnonnull(l);
468
cb.opc_new(nullPointerClass);
469
cb.opc_dup();
470
cb.opc_invokespecial(nullPointerCtorIdx, 0, 0);
471
cb.opc_athrow();
472
l.bind();
473
illegalArgStartPC = cb.getLength();
474
cb.opc_aload_1();
475
cb.opc_checkcast(targetClass);
476
}
477
}
478
479
// Have to check length of incoming array and throw
480
// IllegalArgumentException if not correct. A concession to the
481
// JCK (isn't clearly specified in the spec): we allow null in the
482
// case where the argument list is zero length.
483
// if no-arg:
484
// aload_2 | aload_1 (Method | Constructor)
485
// ifnull <success label>
486
// aload_2 | aload_1
487
// arraylength
488
// sipush <num parameter types>
489
// if_icmpeq <success label>
490
// new <IllegalArgumentException>
491
// dup
492
// invokespecial <IllegalArgumentException ctor>
493
// athrow
494
// <success label:>
495
Label successLabel = new Label();
496
if (parameterTypes.length == 0) {
497
if (isConstructor) {
498
cb.opc_aload_1();
499
} else {
500
cb.opc_aload_2();
501
}
502
cb.opc_ifnull(successLabel);
503
}
504
if (isConstructor) {
505
cb.opc_aload_1();
506
} else {
507
cb.opc_aload_2();
508
}
509
cb.opc_arraylength();
510
cb.opc_sipush((short) parameterTypes.length);
511
cb.opc_if_icmpeq(successLabel);
512
cb.opc_new(illegalArgumentClass);
513
cb.opc_dup();
514
cb.opc_invokespecial(illegalArgumentCtorIdx, 0, 0);
515
cb.opc_athrow();
516
successLabel.bind();
517
518
// Iterate through incoming actual parameters, ensuring that each
519
// is compatible with the formal parameter type, and pushing the
520
// actual on the operand stack (unboxing and widening if necessary).
521
522
short paramTypeCPIdx = nonPrimitiveParametersBaseIdx;
523
Label nextParamLabel = null;
524
byte count = 1; // both invokeinterface opcode's "count" as well as
525
// num args of other invoke bytecodes
526
for (int i = 0; i < parameterTypes.length; i++) {
527
Class<?> paramType = parameterTypes[i];
528
count += (byte) typeSizeInStackSlots(paramType);
529
if (nextParamLabel != null) {
530
nextParamLabel.bind();
531
nextParamLabel = null;
532
}
533
// aload_2 | aload_1
534
// sipush <index>
535
// aaload
536
if (isConstructor) {
537
cb.opc_aload_1();
538
} else {
539
cb.opc_aload_2();
540
}
541
cb.opc_sipush((short) i);
542
cb.opc_aaload();
543
if (isPrimitive(paramType)) {
544
// Unboxing code.
545
// Put parameter into temporary local variable
546
// astore_3 | astore_2
547
if (isConstructor) {
548
cb.opc_astore_2();
549
} else {
550
cb.opc_astore_3();
551
}
552
553
// repeat for all possible widening conversions:
554
// aload_3 | aload_2
555
// instanceof <primitive boxing type>
556
// ifeq <next unboxing label>
557
// aload_3 | aload_2
558
// checkcast <primitive boxing type> // Note: this is "redundant",
559
// // but necessary for the verifier
560
// invokevirtual <unboxing method>
561
// <widening conversion bytecode, if necessary>
562
// goto <next parameter label>
563
// <next unboxing label:> ...
564
// last unboxing label:
565
// new <IllegalArgumentException>
566
// dup
567
// invokespecial <IllegalArgumentException ctor>
568
// athrow
569
570
Label l = null; // unboxing label
571
nextParamLabel = new Label();
572
573
for (int j = 0; j < primitiveTypes.length; j++) {
574
Class<?> c = primitiveTypes[j];
575
if (canWidenTo(c, paramType)) {
576
if (l != null) {
577
l.bind();
578
}
579
// Emit checking and unboxing code for this type
580
if (isConstructor) {
581
cb.opc_aload_2();
582
} else {
583
cb.opc_aload_3();
584
}
585
cb.opc_instanceof(indexForPrimitiveType(c));
586
l = new Label();
587
cb.opc_ifeq(l);
588
if (isConstructor) {
589
cb.opc_aload_2();
590
} else {
591
cb.opc_aload_3();
592
}
593
cb.opc_checkcast(indexForPrimitiveType(c));
594
cb.opc_invokevirtual(unboxingMethodForPrimitiveType(c),
595
0,
596
typeSizeInStackSlots(c));
597
emitWideningBytecodeForPrimitiveConversion(cb,
598
c,
599
paramType);
600
cb.opc_goto(nextParamLabel);
601
}
602
}
603
604
if (l == null) {
605
throw new InternalError
606
("Must have found at least identity conversion");
607
}
608
609
// Fell through; given object is null or invalid. According to
610
// the spec, we can throw IllegalArgumentException for both of
611
// these cases.
612
613
l.bind();
614
cb.opc_new(illegalArgumentClass);
615
cb.opc_dup();
616
cb.opc_invokespecial(illegalArgumentCtorIdx, 0, 0);
617
cb.opc_athrow();
618
} else {
619
// Emit appropriate checkcast
620
cb.opc_checkcast(paramTypeCPIdx);
621
paramTypeCPIdx = add(paramTypeCPIdx, S2);
622
// Fall through to next argument
623
}
624
}
625
// Bind last goto if present
626
if (nextParamLabel != null) {
627
nextParamLabel.bind();
628
}
629
630
short invokeStartPC = cb.getLength();
631
632
// OK, ready to perform the invocation.
633
if (isConstructor) {
634
cb.opc_invokespecial(targetMethodRef, count, 0);
635
} else {
636
if (isStatic()) {
637
cb.opc_invokestatic(targetMethodRef,
638
count,
639
typeSizeInStackSlots(returnType));
640
} else {
641
if (isInterface()) {
642
if (isPrivate()) {
643
cb.opc_invokespecial(targetMethodRef, count, 0);
644
} else {
645
cb.opc_invokeinterface(targetMethodRef,
646
count,
647
count,
648
typeSizeInStackSlots(returnType));
649
}
650
} else {
651
cb.opc_invokevirtual(targetMethodRef,
652
count,
653
typeSizeInStackSlots(returnType));
654
}
655
}
656
}
657
658
short invokeEndPC = cb.getLength();
659
660
if (!isConstructor) {
661
// Box return value if necessary
662
if (isPrimitive(returnType)) {
663
cb.opc_invokespecial(ctorIndexForPrimitiveType(returnType),
664
typeSizeInStackSlots(returnType),
665
0);
666
} else if (returnType == Void.TYPE) {
667
cb.opc_aconst_null();
668
}
669
}
670
cb.opc_areturn();
671
672
// We generate two exception handlers; one which is responsible
673
// for catching ClassCastException and NullPointerException and
674
// throwing IllegalArgumentException, and the other which catches
675
// all java/lang/Throwable objects thrown from the target method
676
// and wraps them in InvocationTargetExceptions.
677
678
short classCastHandler = cb.getLength();
679
680
// ClassCast, etc. exception handler
681
cb.setStack(1);
682
cb.opc_invokespecial(toStringIdx, 0, 1);
683
cb.opc_new(illegalArgumentClass);
684
cb.opc_dup_x1();
685
cb.opc_swap();
686
cb.opc_invokespecial(illegalArgumentStringCtorIdx, 1, 0);
687
cb.opc_athrow();
688
689
short invocationTargetHandler = cb.getLength();
690
691
// InvocationTargetException exception handler
692
cb.setStack(1);
693
cb.opc_new(invocationTargetClass);
694
cb.opc_dup_x1();
695
cb.opc_swap();
696
cb.opc_invokespecial(invocationTargetCtorIdx, 1, 0);
697
cb.opc_athrow();
698
699
// Generate exception table. We cover the entire code sequence
700
// with an exception handler which catches ClassCastException and
701
// converts it into an IllegalArgumentException.
702
703
ClassFileAssembler exc = new ClassFileAssembler();
704
705
exc.emitShort(illegalArgStartPC); // start PC
706
exc.emitShort(invokeStartPC); // end PC
707
exc.emitShort(classCastHandler); // handler PC
708
exc.emitShort(classCastClass); // catch type
709
710
exc.emitShort(illegalArgStartPC); // start PC
711
exc.emitShort(invokeStartPC); // end PC
712
exc.emitShort(classCastHandler); // handler PC
713
exc.emitShort(nullPointerClass); // catch type
714
715
exc.emitShort(invokeStartPC); // start PC
716
exc.emitShort(invokeEndPC); // end PC
717
exc.emitShort(invocationTargetHandler); // handler PC
718
exc.emitShort(throwableClass); // catch type
719
720
emitMethod(invokeIdx, cb.getMaxLocals(), cb, exc,
721
new short[] { invocationTargetClass });
722
}
723
724
private boolean usesPrimitiveTypes() {
725
// We need to emit boxing/unboxing constant pool information if
726
// the method takes a primitive type for any of its parameters or
727
// returns a primitive value (except void)
728
if (returnType.isPrimitive()) {
729
return true;
730
}
731
for (int i = 0; i < parameterTypes.length; i++) {
732
if (parameterTypes[i].isPrimitive()) {
733
return true;
734
}
735
}
736
return false;
737
}
738
739
private int numNonPrimitiveParameterTypes() {
740
int num = 0;
741
for (int i = 0; i < parameterTypes.length; i++) {
742
if (!parameterTypes[i].isPrimitive()) {
743
++num;
744
}
745
}
746
return num;
747
}
748
749
private boolean isInterface() {
750
return declaringClass.isInterface();
751
}
752
753
private String buildInternalSignature() {
754
StringBuffer buf = new StringBuffer();
755
buf.append("(");
756
for (int i = 0; i < parameterTypes.length; i++) {
757
buf.append(getClassName(parameterTypes[i], true));
758
}
759
buf.append(")");
760
buf.append(getClassName(returnType, true));
761
return buf.toString();
762
}
763
764
private static synchronized String generateName(boolean isConstructor,
765
boolean forSerialization)
766
{
767
if (isConstructor) {
768
if (forSerialization) {
769
int num = ++serializationConstructorSymnum;
770
return "sun/reflect/GeneratedSerializationConstructorAccessor" + num;
771
} else {
772
int num = ++constructorSymnum;
773
return "sun/reflect/GeneratedConstructorAccessor" + num;
774
}
775
} else {
776
int num = ++methodSymnum;
777
return "sun/reflect/GeneratedMethodAccessor" + num;
778
}
779
}
780
}
781
782