blob: 3b62e2df8190ba5a4f30d81dd5d1afbca207c756 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2001 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any 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 (MagicAccessorImpl)
396 AccessController.doPrivileged(new PrivilegedAction() {
397 public Object run() {
398 try {
399 return ClassDefiner.defineClass
400 (generatedName,
401 bytes,
402 0,
403 bytes.length,
404 declaringClass.getClassLoader()).newInstance();
405 } catch (InstantiationException e) {
406 throw (InternalError)
407 new InternalError().initCause(e);
408 } catch (IllegalAccessException e) {
409 throw (InternalError)
410 new InternalError().initCause(e);
411 }
412 }
413 });
414 }
415
416 /** This emits the code for either invoke() or newInstance() */
417 private void emitInvoke() {
418 // NOTE that this code will only handle 65535 parameters since we
419 // use the sipush instruction to get the array index on the
420 // operand stack.
421 if (parameterTypes.length > 65535) {
422 throw new InternalError("Can't handle more than 65535 parameters");
423 }
424
425 // Generate code into fresh code buffer
426 ClassFileAssembler cb = new ClassFileAssembler();
427 if (isConstructor) {
428 // 1 incoming argument
429 cb.setMaxLocals(2);
430 } else {
431 // 2 incoming arguments
432 cb.setMaxLocals(3);
433 }
434
435 short illegalArgStartPC = 0;
436
437 if (isConstructor) {
438 // Instantiate target class before continuing
439 // new <target class type>
440 // dup
441 cb.opc_new(targetClass);
442 cb.opc_dup();
443 } else {
444 // Setup before iterating down argument list
445 if (isPrimitive(returnType)) {
446 // new <boxing type for primitive type>
447 // dup
448 // ... (see below:)
449 // invokespecial <constructor for boxing type for primitive type>
450 // areturn
451 cb.opc_new(indexForPrimitiveType(returnType));
452 cb.opc_dup();
453 }
454
455 // Get target object on operand stack if necessary.
456
457 // We need to do an explicit null check here; we won't see
458 // NullPointerExceptions from the invoke bytecode, since it's
459 // covered by an exception handler.
460 if (!isStatic()) {
461 // aload_1
462 // ifnonnull <checkcast label>
463 // new <NullPointerException>
464 // dup
465 // invokespecial <NullPointerException ctor>
466 // athrow
467 // <checkcast label:>
468 // aload_1
469 // checkcast <target class's type>
470 cb.opc_aload_1();
471 Label l = new Label();
472 cb.opc_ifnonnull(l);
473 cb.opc_new(nullPointerClass);
474 cb.opc_dup();
475 cb.opc_invokespecial(nullPointerCtorIdx, 0, 0);
476 cb.opc_athrow();
477 l.bind();
478 illegalArgStartPC = cb.getLength();
479 cb.opc_aload_1();
480 cb.opc_checkcast(targetClass);
481 }
482 }
483
484 // Have to check length of incoming array and throw
485 // IllegalArgumentException if not correct. A concession to the
486 // JCK (isn't clearly specified in the spec): we allow null in the
487 // case where the argument list is zero length.
488 // if no-arg:
489 // aload_2 | aload_1 (Method | Constructor)
490 // ifnull <success label>
491 // aload_2 | aload_1
492 // arraylength
493 // sipush <num parameter types>
494 // if_icmpeq <success label>
495 // new <IllegalArgumentException>
496 // dup
497 // invokespecial <IllegalArgumentException ctor>
498 // athrow
499 // <success label:>
500 Label successLabel = new Label();
501 if (parameterTypes.length == 0) {
502 if (isConstructor) {
503 cb.opc_aload_1();
504 } else {
505 cb.opc_aload_2();
506 }
507 cb.opc_ifnull(successLabel);
508 }
509 if (isConstructor) {
510 cb.opc_aload_1();
511 } else {
512 cb.opc_aload_2();
513 }
514 cb.opc_arraylength();
515 cb.opc_sipush((short) parameterTypes.length);
516 cb.opc_if_icmpeq(successLabel);
517 cb.opc_new(illegalArgumentClass);
518 cb.opc_dup();
519 cb.opc_invokespecial(illegalArgumentCtorIdx, 0, 0);
520 cb.opc_athrow();
521 successLabel.bind();
522
523 // Iterate through incoming actual parameters, ensuring that each
524 // is compatible with the formal parameter type, and pushing the
525 // actual on the operand stack (unboxing and widening if necessary).
526
527 short paramTypeCPIdx = nonPrimitiveParametersBaseIdx;
528 Label nextParamLabel = null;
529 byte count = 1; // both invokeinterface opcode's "count" as well as
530 // num args of other invoke bytecodes
531 for (int i = 0; i < parameterTypes.length; i++) {
532 Class paramType = parameterTypes[i];
533 count += (byte) typeSizeInStackSlots(paramType);
534 if (nextParamLabel != null) {
535 nextParamLabel.bind();
536 nextParamLabel = null;
537 }
538 // aload_2 | aload_1
539 // sipush <index>
540 // aaload
541 if (isConstructor) {
542 cb.opc_aload_1();
543 } else {
544 cb.opc_aload_2();
545 }
546 cb.opc_sipush((short) i);
547 cb.opc_aaload();
548 if (isPrimitive(paramType)) {
549 // Unboxing code.
550 // Put parameter into temporary local variable
551 // astore_3 | astore_2
552 if (isConstructor) {
553 cb.opc_astore_2();
554 } else {
555 cb.opc_astore_3();
556 }
557
558 // repeat for all possible widening conversions:
559 // aload_3 | aload_2
560 // instanceof <primitive boxing type>
561 // ifeq <next unboxing label>
562 // aload_3 | aload_2
563 // checkcast <primitive boxing type> // Note: this is "redundant",
564 // // but necessary for the verifier
565 // invokevirtual <unboxing method>
566 // <widening conversion bytecode, if necessary>
567 // goto <next parameter label>
568 // <next unboxing label:> ...
569 // last unboxing label:
570 // new <IllegalArgumentException>
571 // dup
572 // invokespecial <IllegalArgumentException ctor>
573 // athrow
574
575 Label l = null; // unboxing label
576 nextParamLabel = new Label();
577
578 for (int j = 0; j < primitiveTypes.length; j++) {
579 Class c = primitiveTypes[j];
580 if (canWidenTo(c, paramType)) {
581 if (l != null) {
582 l.bind();
583 }
584 // Emit checking and unboxing code for this type
585 if (isConstructor) {
586 cb.opc_aload_2();
587 } else {
588 cb.opc_aload_3();
589 }
590 cb.opc_instanceof(indexForPrimitiveType(c));
591 l = new Label();
592 cb.opc_ifeq(l);
593 if (isConstructor) {
594 cb.opc_aload_2();
595 } else {
596 cb.opc_aload_3();
597 }
598 cb.opc_checkcast(indexForPrimitiveType(c));
599 cb.opc_invokevirtual(unboxingMethodForPrimitiveType(c),
600 0,
601 typeSizeInStackSlots(c));
602 emitWideningBytecodeForPrimitiveConversion(cb,
603 c,
604 paramType);
605 cb.opc_goto(nextParamLabel);
606 }
607 }
608
609 if (l == null) {
610 throw new InternalError
611 ("Must have found at least identity conversion");
612 }
613
614 // Fell through; given object is null or invalid. According to
615 // the spec, we can throw IllegalArgumentException for both of
616 // these cases.
617
618 l.bind();
619 cb.opc_new(illegalArgumentClass);
620 cb.opc_dup();
621 cb.opc_invokespecial(illegalArgumentCtorIdx, 0, 0);
622 cb.opc_athrow();
623 } else {
624 // Emit appropriate checkcast
625 cb.opc_checkcast(paramTypeCPIdx);
626 paramTypeCPIdx = add(paramTypeCPIdx, S2);
627 // Fall through to next argument
628 }
629 }
630 // Bind last goto if present
631 if (nextParamLabel != null) {
632 nextParamLabel.bind();
633 }
634
635 short invokeStartPC = cb.getLength();
636
637 // OK, ready to perform the invocation.
638 if (isConstructor) {
639 cb.opc_invokespecial(targetMethodRef, count, 0);
640 } else {
641 if (isStatic()) {
642 cb.opc_invokestatic(targetMethodRef,
643 count,
644 typeSizeInStackSlots(returnType));
645 } else {
646 if (isInterface()) {
647 cb.opc_invokeinterface(targetMethodRef,
648 count,
649 count,
650 typeSizeInStackSlots(returnType));
651 } else {
652 cb.opc_invokevirtual(targetMethodRef,
653 count,
654 typeSizeInStackSlots(returnType));
655 }
656 }
657 }
658
659 short invokeEndPC = cb.getLength();
660
661 if (!isConstructor) {
662 // Box return value if necessary
663 if (isPrimitive(returnType)) {
664 cb.opc_invokespecial(ctorIndexForPrimitiveType(returnType),
665 typeSizeInStackSlots(returnType),
666 0);
667 } else if (returnType == Void.TYPE) {
668 cb.opc_aconst_null();
669 }
670 }
671 cb.opc_areturn();
672
673 // We generate two exception handlers; one which is responsible
674 // for catching ClassCastException and NullPointerException and
675 // throwing IllegalArgumentException, and the other which catches
676 // all java/lang/Throwable objects thrown from the target method
677 // and wraps them in InvocationTargetExceptions.
678
679 short classCastHandler = cb.getLength();
680
681 // ClassCast, etc. exception handler
682 cb.setStack(1);
683 cb.opc_invokespecial(toStringIdx, 0, 1);
684 cb.opc_new(illegalArgumentClass);
685 cb.opc_dup_x1();
686 cb.opc_swap();
687 cb.opc_invokespecial(illegalArgumentStringCtorIdx, 1, 0);
688 cb.opc_athrow();
689
690 short invocationTargetHandler = cb.getLength();
691
692 // InvocationTargetException exception handler
693 cb.setStack(1);
694 cb.opc_new(invocationTargetClass);
695 cb.opc_dup_x1();
696 cb.opc_swap();
697 cb.opc_invokespecial(invocationTargetCtorIdx, 1, 0);
698 cb.opc_athrow();
699
700 // Generate exception table. We cover the entire code sequence
701 // with an exception handler which catches ClassCastException and
702 // converts it into an IllegalArgumentException.
703
704 ClassFileAssembler exc = new ClassFileAssembler();
705
706 exc.emitShort(illegalArgStartPC); // start PC
707 exc.emitShort(invokeStartPC); // end PC
708 exc.emitShort(classCastHandler); // handler PC
709 exc.emitShort(classCastClass); // catch type
710
711 exc.emitShort(illegalArgStartPC); // start PC
712 exc.emitShort(invokeStartPC); // end PC
713 exc.emitShort(classCastHandler); // handler PC
714 exc.emitShort(nullPointerClass); // catch type
715
716 exc.emitShort(invokeStartPC); // start PC
717 exc.emitShort(invokeEndPC); // end PC
718 exc.emitShort(invocationTargetHandler); // handler PC
719 exc.emitShort(throwableClass); // catch type
720
721 emitMethod(invokeIdx, cb.getMaxLocals(), cb, exc,
722 new short[] { invocationTargetClass });
723 }
724
725 private boolean usesPrimitiveTypes() {
726 // We need to emit boxing/unboxing constant pool information if
727 // the method takes a primitive type for any of its parameters or
728 // returns a primitive value (except void)
729 if (returnType.isPrimitive()) {
730 return true;
731 }
732 for (int i = 0; i < parameterTypes.length; i++) {
733 if (parameterTypes[i].isPrimitive()) {
734 return true;
735 }
736 }
737 return false;
738 }
739
740 private int numNonPrimitiveParameterTypes() {
741 int num = 0;
742 for (int i = 0; i < parameterTypes.length; i++) {
743 if (!parameterTypes[i].isPrimitive()) {
744 ++num;
745 }
746 }
747 return num;
748 }
749
750 private boolean isInterface() {
751 return declaringClass.isInterface();
752 }
753
754 private String buildInternalSignature() {
755 StringBuffer buf = new StringBuffer();
756 buf.append("(");
757 for (int i = 0; i < parameterTypes.length; i++) {
758 buf.append(getClassName(parameterTypes[i], true));
759 }
760 buf.append(")");
761 buf.append(getClassName(returnType, true));
762 return buf.toString();
763 }
764
765 private static synchronized String generateName(boolean isConstructor,
766 boolean forSerialization)
767 {
768 if (isConstructor) {
769 if (forSerialization) {
770 int num = ++serializationConstructorSymnum;
771 return "sun/reflect/GeneratedSerializationConstructorAccessor" + num;
772 } else {
773 int num = ++constructorSymnum;
774 return "sun/reflect/GeneratedConstructorAccessor" + num;
775 }
776 } else {
777 int num = ++methodSymnum;
778 return "sun/reflect/GeneratedMethodAccessor" + num;
779 }
780 }
781}