Save This Page
Home » openjdk-7 » sun » reflect » [javadoc | source]
    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   
   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   }

Save This Page
Home » openjdk-7 » sun » reflect » [javadoc | source]