History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/reflect/MethodAccessorGenerator.java (1 of 18352 files). Show all

Unified · Split

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