< prev index next >

src/java.base/share/classes/java/lang/reflect/ProxyGenerator.java

Print this page

   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 java.lang.reflect;
  27 
  28 import jdk.internal.misc.VM;


  29 import jdk.internal.org.objectweb.asm.ClassWriter;
  30 import jdk.internal.org.objectweb.asm.Label;
  31 import jdk.internal.org.objectweb.asm.MethodVisitor;
  32 import jdk.internal.org.objectweb.asm.Opcodes;
  33 import jdk.internal.org.objectweb.asm.Type;
  34 import sun.security.action.GetBooleanAction;
  35 
  36 import java.io.IOException;
  37 import java.lang.invoke.MethodType;
  38 import java.nio.file.Files;
  39 import java.nio.file.Path;
  40 import java.util.ArrayList;
  41 import java.util.Arrays;
  42 import java.util.HashMap;

  43 import java.util.LinkedHashMap;
  44 import java.util.List;
  45 import java.util.ListIterator;
  46 import java.util.Map;

  47 
  48 import static jdk.internal.org.objectweb.asm.Opcodes.*;
  49 
  50 /**
  51  * ProxyGenerator contains the code to generate a dynamic proxy class
  52  * for the java.lang.reflect.Proxy API.
  53  * <p>
  54  * The external interface to ProxyGenerator is the static
  55  * "generateProxyClass" method.
  56  */
  57 final class ProxyGenerator extends ClassWriter {
  58     private static final int CLASSFILE_VERSION = VM.classFileVersion();
  59     private static final String JL_CLASS = "java/lang/Class";
  60     private static final String JL_OBJECT = "java/lang/Object";
  61     private static final String JL_THROWABLE = "java/lang/Throwable";
  62     private static final String JL_CLASS_NOT_FOUND_EX = "java/lang/ClassNotFoundException";
  63     private static final String JL_ILLEGAL_ACCESS_EX = "java/lang/IllegalAccessException";
  64 
  65     private static final String JL_NO_CLASS_DEF_FOUND_ERROR = "java/lang/NoClassDefFoundError";
  66     private static final String JL_NO_SUCH_METHOD_EX = "java/lang/NoSuchMethodException";

 473          * Accumulate all of the methods from the proxy interfaces.
 474          */
 475         for (Class<?> intf : interfaces) {
 476             for (Method m : intf.getMethods()) {
 477                 if (!Modifier.isStatic(m.getModifiers())) {
 478                     addProxyMethod(m, intf);
 479                 }
 480             }
 481         }
 482 
 483         /*
 484          * For each set of proxy methods with the same signature,
 485          * verify that the methods' return types are compatible.
 486          */
 487         for (List<ProxyMethod> sigmethods : proxyMethods.values()) {
 488             checkReturnTypes(sigmethods);
 489         }
 490 
 491         generateConstructor();
 492 

 493         for (List<ProxyMethod> sigmethods : proxyMethods.values()) {
 494             for (ProxyMethod pm : sigmethods) {
 495                 // add static field for the Method object
 496                 visitField(ACC_PRIVATE | ACC_STATIC | ACC_FINAL, pm.methodFieldName,
 497                         LJLR_METHOD, null, null);
 498 
 499                 // Generate code for proxy method
 500                 pm.generateMethod(this, className);

 501             }
 502         }



 503 
 504         generateStaticInitializer();
 505         generateLookupAccessor();
 506         return toByteArray();
 507     }
 508 
 509     /**
 510      * Add another method to be proxied, either by creating a new
 511      * ProxyMethod object or augmenting an old one for a duplicate
 512      * method.
 513      *
 514      * "fromClass" indicates the proxy interface that the method was
 515      * found through, which may be different from (a subinterface of)
 516      * the method's "declaring class".  Note that the first Method
 517      * object passed for a given name and descriptor identifies the
 518      * Method object (and thus the declaring class) that will be
 519      * passed to the invocation handler's "invoke" method for a given
 520      * set of duplicate methods.
 521      */
 522     private void addProxyMethod(Method m, Class<?> fromClass) {

 657         mv.visitJumpInsn(IFEQ, L_illegalAccess);
 658         mv.visitMethodInsn(INVOKESTATIC, JLI_METHODHANDLES, "lookup",
 659                 "()Ljava/lang/invoke/MethodHandles$Lookup;", false);
 660         mv.visitInsn(ARETURN);
 661 
 662         mv.visitLabel(L_illegalAccess);
 663         mv.visitTypeInsn(Opcodes.NEW, JL_ILLEGAL_ACCESS_EX);
 664         mv.visitInsn(DUP);
 665         mv.visitVarInsn(ALOAD, 0);
 666         mv.visitMethodInsn(INVOKEVIRTUAL, JLI_LOOKUP, "toString",
 667                 "()Ljava/lang/String;", false);
 668         mv.visitMethodInsn(INVOKESPECIAL, JL_ILLEGAL_ACCESS_EX,
 669                 "<init>", "(Ljava/lang/String;)V", false);
 670         mv.visitInsn(ATHROW);
 671 
 672         // Maxs computed by ClassWriter.COMPUTE_FRAMES, these arguments ignored
 673         mv.visitMaxs(-1, -1);
 674         mv.visitEnd();
 675     }
 676 


















 677     /**
 678      * A ProxyMethod object represents a proxy method in the proxy class
 679      * being generated: a method whose implementation will encode and
 680      * dispatch invocations to the proxy instance's invocation handler.
 681      */
 682     private static class ProxyMethod {
 683 
 684         private final Method method;
 685         private final String shortSignature;
 686         private final Class<?> fromClass;
 687         private final Class<?>[] parameterTypes;
 688         private final Class<?> returnType;
 689         private final String methodFieldName;
 690         private Class<?>[] exceptionTypes;
 691 
 692         private ProxyMethod(Method method, String sig, Class<?>[] parameterTypes,
 693                             Class<?> returnType, Class<?>[] exceptionTypes,
 694                             Class<?> fromClass, String methodFieldName) {
 695             this.method = method;
 696             this.shortSignature = sig;

 786 
 787             mv.visitLabel(L_endBlock);
 788 
 789             // Generate exception handler
 790             mv.visitLabel(L_RuntimeHandler);
 791             mv.visitInsn(ATHROW);   // just rethrow the exception
 792 
 793             mv.visitLabel(L_ThrowableHandler);
 794             mv.visitVarInsn(ASTORE, 1);
 795             mv.visitTypeInsn(Opcodes.NEW, JLR_UNDECLARED_THROWABLE_EX);
 796             mv.visitInsn(DUP);
 797             mv.visitVarInsn(ALOAD, 1);
 798             mv.visitMethodInsn(INVOKESPECIAL, JLR_UNDECLARED_THROWABLE_EX,
 799                     "<init>", "(Ljava/lang/Throwable;)V", false);
 800             mv.visitInsn(ATHROW);
 801             // Maxs computed by ClassWriter.COMPUTE_FRAMES, these arguments ignored
 802             mv.visitMaxs(-1, -1);
 803             mv.visitEnd();
 804         }
 805 





















 806         /**
 807          * Generate code for wrapping an argument of the given type
 808          * whose value can be found at the specified local variable
 809          * index, in order for it to be passed (as an Object) to the
 810          * invocation handler's "invoke" method.
 811          */
 812         private void codeWrapArgument(MethodVisitor mv, Class<?> type, int slot) {
 813             if (type.isPrimitive()) {
 814                 PrimitiveTypeInfo prim = PrimitiveTypeInfo.get(type);
 815 
 816                 if (type == int.class ||
 817                         type == boolean.class ||
 818                         type == byte.class ||
 819                         type == char.class ||
 820                         type == short.class) {
 821                     mv.visitVarInsn(ILOAD, slot);
 822                 } else if (type == long.class) {
 823                     mv.visitVarInsn(LLOAD, slot);
 824                 } else if (type == float.class) {
 825                     mv.visitVarInsn(FLOAD, slot);

 848                 mv.visitMethodInsn(INVOKEVIRTUAL,
 849                         prim.wrapperClassName,
 850                         prim.unwrapMethodName, prim.unwrapMethodDesc, false);
 851 
 852                 if (type == int.class ||
 853                         type == boolean.class ||
 854                         type == byte.class ||
 855                         type == char.class ||
 856                         type == short.class) {
 857                     mv.visitInsn(IRETURN);
 858                 } else if (type == long.class) {
 859                     mv.visitInsn(LRETURN);
 860                 } else if (type == float.class) {
 861                     mv.visitInsn(FRETURN);
 862                 } else if (type == double.class) {
 863                     mv.visitInsn(DRETURN);
 864                 } else {
 865                     throw new AssertionError();
 866                 }
 867             } else {
 868                 mv.visitTypeInsn(CHECKCAST, dotToSlash(type.getName()));




 869                 mv.visitInsn(ARETURN);
 870             }
 871         }
 872 
 873         /**
 874          * Generate code for initializing the static field that stores
 875          * the Method object for this proxy method.
 876          */
 877         private void codeFieldInitialization(MethodVisitor mv, String className) {
 878             codeClassForName(mv, fromClass);
 879 
 880             mv.visitLdcInsn(method.getName());
 881 
 882             emitIconstInsn(mv, parameterTypes.length);
 883 
 884             mv.visitTypeInsn(Opcodes.ANEWARRAY, JL_CLASS);
 885 
 886             // Construct an array with the parameter types mapping primitives to Wrapper types
 887             for (int i = 0; i < parameterTypes.length; i++) {
 888                 mv.visitInsn(DUP);

 899                 mv.visitInsn(Opcodes.AASTORE);
 900             }
 901             // lookup the method
 902             mv.visitMethodInsn(INVOKEVIRTUAL,
 903                     JL_CLASS,
 904                     "getMethod",
 905                     "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;",
 906                     false);
 907 
 908             mv.visitFieldInsn(PUTSTATIC,
 909                     dotToSlash(className),
 910                     methodFieldName, LJLR_METHOD);
 911         }
 912 
 913         /*
 914          * =============== Code Generation Utility Methods ===============
 915          */
 916 
 917         /**
 918          * Generate code to invoke the Class.forName with the name of the given
 919          * class to get its Class object at runtime.  The code is written to
 920          * the supplied stream.  Note that the code generated by this method
 921          * may cause the checked ClassNotFoundException to be thrown.


 922          */
 923         private void codeClassForName(MethodVisitor mv, Class<?> cl) {
 924             mv.visitLdcInsn(cl.getName());
 925             mv.visitMethodInsn(INVOKESTATIC,
 926                     JL_CLASS,
 927                     "forName", "(Ljava/lang/String;)Ljava/lang/Class;", false);





 928         }
 929 
 930         /**
 931          * Visit a bytecode for a constant.
 932          *
 933          * @param mv  The MethodVisitor
 934          * @param cst The constant value
 935          */
 936         private void emitIconstInsn(MethodVisitor mv, final int cst) {
 937             if (cst >= -1 && cst <= 5) {
 938                 mv.visitInsn(Opcodes.ICONST_0 + cst);
 939             } else if (cst >= Byte.MIN_VALUE && cst <= Byte.MAX_VALUE) {
 940                 mv.visitIntInsn(Opcodes.BIPUSH, cst);
 941             } else if (cst >= Short.MIN_VALUE && cst <= Short.MAX_VALUE) {
 942                 mv.visitIntInsn(Opcodes.SIPUSH, cst);
 943             } else {
 944                 mv.visitLdcInsn(cst);
 945             }
 946         }
 947 

   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 java.lang.reflect;
  27 
  28 import jdk.internal.misc.VM;
  29 import jdk.internal.org.objectweb.asm.Attribute;
  30 import jdk.internal.org.objectweb.asm.ByteVector;
  31 import jdk.internal.org.objectweb.asm.ClassWriter;
  32 import jdk.internal.org.objectweb.asm.Label;
  33 import jdk.internal.org.objectweb.asm.MethodVisitor;
  34 import jdk.internal.org.objectweb.asm.Opcodes;
  35 import jdk.internal.org.objectweb.asm.Type;
  36 import sun.security.action.GetBooleanAction;
  37 
  38 import java.io.IOException;
  39 import java.lang.invoke.MethodType;
  40 import java.nio.file.Files;
  41 import java.nio.file.Path;
  42 import java.util.ArrayList;
  43 import java.util.Arrays;
  44 import java.util.HashMap;
  45 import java.util.HashSet;
  46 import java.util.LinkedHashMap;
  47 import java.util.List;
  48 import java.util.ListIterator;
  49 import java.util.Map;
  50 import java.util.Set;
  51 
  52 import static jdk.internal.org.objectweb.asm.Opcodes.*;
  53 
  54 /**
  55  * ProxyGenerator contains the code to generate a dynamic proxy class
  56  * for the java.lang.reflect.Proxy API.
  57  * <p>
  58  * The external interface to ProxyGenerator is the static
  59  * "generateProxyClass" method.
  60  */
  61 final class ProxyGenerator extends ClassWriter {
  62     private static final int CLASSFILE_VERSION = VM.classFileVersion();
  63     private static final String JL_CLASS = "java/lang/Class";
  64     private static final String JL_OBJECT = "java/lang/Object";
  65     private static final String JL_THROWABLE = "java/lang/Throwable";
  66     private static final String JL_CLASS_NOT_FOUND_EX = "java/lang/ClassNotFoundException";
  67     private static final String JL_ILLEGAL_ACCESS_EX = "java/lang/IllegalAccessException";
  68 
  69     private static final String JL_NO_CLASS_DEF_FOUND_ERROR = "java/lang/NoClassDefFoundError";
  70     private static final String JL_NO_SUCH_METHOD_EX = "java/lang/NoSuchMethodException";

 477          * Accumulate all of the methods from the proxy interfaces.
 478          */
 479         for (Class<?> intf : interfaces) {
 480             for (Method m : intf.getMethods()) {
 481                 if (!Modifier.isStatic(m.getModifiers())) {
 482                     addProxyMethod(m, intf);
 483                 }
 484             }
 485         }
 486 
 487         /*
 488          * For each set of proxy methods with the same signature,
 489          * verify that the methods' return types are compatible.
 490          */
 491         for (List<ProxyMethod> sigmethods : proxyMethods.values()) {
 492             checkReturnTypes(sigmethods);
 493         }
 494 
 495         generateConstructor();
 496 
 497         Set<Class<?>> preloadClasses = new HashSet<>();
 498         for (List<ProxyMethod> sigmethods : proxyMethods.values()) {
 499             for (ProxyMethod pm : sigmethods) {
 500                 // add static field for the Method object
 501                 visitField(ACC_PRIVATE | ACC_STATIC | ACC_FINAL, pm.methodFieldName,
 502                         LJLR_METHOD, null, null);
 503 
 504                 // Generate code for proxy method
 505                 pm.generateMethod(this, className);
 506                 preloadClasses.addAll(pm.preloadClasses());
 507             }
 508         }
 509         if (preloadClasses.size() > 0) {
 510             generatePreloadAttribute(preloadClasses);
 511         }
 512 
 513         generateStaticInitializer();
 514         generateLookupAccessor();
 515         return toByteArray();
 516     }
 517 
 518     /**
 519      * Add another method to be proxied, either by creating a new
 520      * ProxyMethod object or augmenting an old one for a duplicate
 521      * method.
 522      *
 523      * "fromClass" indicates the proxy interface that the method was
 524      * found through, which may be different from (a subinterface of)
 525      * the method's "declaring class".  Note that the first Method
 526      * object passed for a given name and descriptor identifies the
 527      * Method object (and thus the declaring class) that will be
 528      * passed to the invocation handler's "invoke" method for a given
 529      * set of duplicate methods.
 530      */
 531     private void addProxyMethod(Method m, Class<?> fromClass) {

 666         mv.visitJumpInsn(IFEQ, L_illegalAccess);
 667         mv.visitMethodInsn(INVOKESTATIC, JLI_METHODHANDLES, "lookup",
 668                 "()Ljava/lang/invoke/MethodHandles$Lookup;", false);
 669         mv.visitInsn(ARETURN);
 670 
 671         mv.visitLabel(L_illegalAccess);
 672         mv.visitTypeInsn(Opcodes.NEW, JL_ILLEGAL_ACCESS_EX);
 673         mv.visitInsn(DUP);
 674         mv.visitVarInsn(ALOAD, 0);
 675         mv.visitMethodInsn(INVOKEVIRTUAL, JLI_LOOKUP, "toString",
 676                 "()Ljava/lang/String;", false);
 677         mv.visitMethodInsn(INVOKESPECIAL, JL_ILLEGAL_ACCESS_EX,
 678                 "<init>", "(Ljava/lang/String;)V", false);
 679         mv.visitInsn(ATHROW);
 680 
 681         // Maxs computed by ClassWriter.COMPUTE_FRAMES, these arguments ignored
 682         mv.visitMaxs(-1, -1);
 683         mv.visitEnd();
 684     }
 685 
 686     private void generatePreloadAttribute(Set<Class<?>> preloadClasses) {
 687         Attribute attr = new Attribute("Preload") {
 688             @Override
 689             protected ByteVector write(ClassWriter cw,
 690                                        byte[] code,
 691                                        int len,
 692                                        int maxStack,
 693                                        int maxLocals) {
 694                 ByteVector attr = new ByteVector();
 695                 attr.putShort(preloadClasses.size());
 696                 for (Class<?> c : preloadClasses) {
 697                     attr.putShort(cw.newClass(Type.getInternalName(c)));
 698                 }
 699                 return attr;
 700             }
 701         };
 702         visitAttribute(attr);
 703     }
 704     /**
 705      * A ProxyMethod object represents a proxy method in the proxy class
 706      * being generated: a method whose implementation will encode and
 707      * dispatch invocations to the proxy instance's invocation handler.
 708      */
 709     private static class ProxyMethod {
 710 
 711         private final Method method;
 712         private final String shortSignature;
 713         private final Class<?> fromClass;
 714         private final Class<?>[] parameterTypes;
 715         private final Class<?> returnType;
 716         private final String methodFieldName;
 717         private Class<?>[] exceptionTypes;
 718 
 719         private ProxyMethod(Method method, String sig, Class<?>[] parameterTypes,
 720                             Class<?> returnType, Class<?>[] exceptionTypes,
 721                             Class<?> fromClass, String methodFieldName) {
 722             this.method = method;
 723             this.shortSignature = sig;

 813 
 814             mv.visitLabel(L_endBlock);
 815 
 816             // Generate exception handler
 817             mv.visitLabel(L_RuntimeHandler);
 818             mv.visitInsn(ATHROW);   // just rethrow the exception
 819 
 820             mv.visitLabel(L_ThrowableHandler);
 821             mv.visitVarInsn(ASTORE, 1);
 822             mv.visitTypeInsn(Opcodes.NEW, JLR_UNDECLARED_THROWABLE_EX);
 823             mv.visitInsn(DUP);
 824             mv.visitVarInsn(ALOAD, 1);
 825             mv.visitMethodInsn(INVOKESPECIAL, JLR_UNDECLARED_THROWABLE_EX,
 826                     "<init>", "(Ljava/lang/Throwable;)V", false);
 827             mv.visitInsn(ATHROW);
 828             // Maxs computed by ClassWriter.COMPUTE_FRAMES, these arguments ignored
 829             mv.visitMaxs(-1, -1);
 830             mv.visitEnd();
 831         }
 832 
 833         Set<Class<?>> preloadClasses() {
 834             Set<Class<?>> preloadClasses = new HashSet<>();
 835             for (Class<?> type : parameterTypes) {
 836                 if (requiresPreload(type)) {
 837                     preloadClasses.add(type);
 838                 }
 839             }
 840             if (requiresPreload(returnType)) {
 841                 preloadClasses.add(returnType);
 842             }
 843             return preloadClasses;
 844         }
 845 
 846         boolean requiresPreload(Class<?> cls) {
 847             Class<?> c = cls;
 848             while (c.isArray()) {
 849                 c = c.getComponentType();
 850             }
 851             return (c.isValue() && !c.isPrimitiveClass()) || c.isPrimitiveValueType();
 852         }
 853 
 854         /**
 855          * Generate code for wrapping an argument of the given type
 856          * whose value can be found at the specified local variable
 857          * index, in order for it to be passed (as an Object) to the
 858          * invocation handler's "invoke" method.
 859          */
 860         private void codeWrapArgument(MethodVisitor mv, Class<?> type, int slot) {
 861             if (type.isPrimitive()) {
 862                 PrimitiveTypeInfo prim = PrimitiveTypeInfo.get(type);
 863 
 864                 if (type == int.class ||
 865                         type == boolean.class ||
 866                         type == byte.class ||
 867                         type == char.class ||
 868                         type == short.class) {
 869                     mv.visitVarInsn(ILOAD, slot);
 870                 } else if (type == long.class) {
 871                     mv.visitVarInsn(LLOAD, slot);
 872                 } else if (type == float.class) {
 873                     mv.visitVarInsn(FLOAD, slot);

 896                 mv.visitMethodInsn(INVOKEVIRTUAL,
 897                         prim.wrapperClassName,
 898                         prim.unwrapMethodName, prim.unwrapMethodDesc, false);
 899 
 900                 if (type == int.class ||
 901                         type == boolean.class ||
 902                         type == byte.class ||
 903                         type == char.class ||
 904                         type == short.class) {
 905                     mv.visitInsn(IRETURN);
 906                 } else if (type == long.class) {
 907                     mv.visitInsn(LRETURN);
 908                 } else if (type == float.class) {
 909                     mv.visitInsn(FRETURN);
 910                 } else if (type == double.class) {
 911                     mv.visitInsn(DRETURN);
 912                 } else {
 913                     throw new AssertionError();
 914                 }
 915             } else {
 916                 String internalName = dotToSlash(type.getName());
 917                 if (type.isPrimitiveValueType()) {
 918                     internalName = 'Q' + internalName + ";";
 919                 }
 920                 mv.visitTypeInsn(CHECKCAST, internalName);
 921                 mv.visitInsn(ARETURN);
 922             }
 923         }
 924 
 925         /**
 926          * Generate code for initializing the static field that stores
 927          * the Method object for this proxy method.
 928          */
 929         private void codeFieldInitialization(MethodVisitor mv, String className) {
 930             codeClassForName(mv, fromClass);
 931 
 932             mv.visitLdcInsn(method.getName());
 933 
 934             emitIconstInsn(mv, parameterTypes.length);
 935 
 936             mv.visitTypeInsn(Opcodes.ANEWARRAY, JL_CLASS);
 937 
 938             // Construct an array with the parameter types mapping primitives to Wrapper types
 939             for (int i = 0; i < parameterTypes.length; i++) {
 940                 mv.visitInsn(DUP);

 951                 mv.visitInsn(Opcodes.AASTORE);
 952             }
 953             // lookup the method
 954             mv.visitMethodInsn(INVOKEVIRTUAL,
 955                     JL_CLASS,
 956                     "getMethod",
 957                     "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;",
 958                     false);
 959 
 960             mv.visitFieldInsn(PUTSTATIC,
 961                     dotToSlash(className),
 962                     methodFieldName, LJLR_METHOD);
 963         }
 964 
 965         /*
 966          * =============== Code Generation Utility Methods ===============
 967          */
 968 
 969         /**
 970          * Generate code to invoke the Class.forName with the name of the given
 971          * class to get its Class object at runtime.  And also generate code
 972          * to invoke Class::asValueType if the class is a primitive value type.
 973          *
 974          * The code is written to the supplied stream.  Note that the code generated
 975          * by this method may caused the checked ClassNotFoundException to be thrown.
 976          */
 977         private void codeClassForName(MethodVisitor mv, Class<?> cl) {
 978             mv.visitLdcInsn(cl.getName());
 979             mv.visitMethodInsn(INVOKESTATIC,
 980                     JL_CLASS,
 981                     "forName", "(Ljava/lang/String;)Ljava/lang/Class;", false);
 982             if (cl.isPrimitiveValueType()) {
 983               mv.visitMethodInsn(INVOKEVIRTUAL,
 984                                  JL_CLASS,
 985                                  "asValueType", "()Ljava/lang/Class;", false);
 986             }
 987         }
 988 
 989         /**
 990          * Visit a bytecode for a constant.
 991          *
 992          * @param mv  The MethodVisitor
 993          * @param cst The constant value
 994          */
 995         private void emitIconstInsn(MethodVisitor mv, final int cst) {
 996             if (cst >= -1 && cst <= 5) {
 997                 mv.visitInsn(Opcodes.ICONST_0 + cst);
 998             } else if (cst >= Byte.MIN_VALUE && cst <= Byte.MAX_VALUE) {
 999                 mv.visitIntInsn(Opcodes.BIPUSH, cst);
1000             } else if (cst >= Short.MIN_VALUE && cst <= Short.MAX_VALUE) {
1001                 mv.visitIntInsn(Opcodes.SIPUSH, cst);
1002             } else {
1003                 mv.visitLdcInsn(cst);
1004             }
1005         }
1006 
< prev index next >