1 /*
   2  * Copyright (c) 2001, 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.lang.reflect.*;
  29 import java.security.AccessController;
  30 import java.security.PrivilegedAction;
  31 import 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 
  41 class 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 }