< prev index next >

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

Print this page

   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 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.invoke.util.Wrapper;
  35 import sun.security.action.GetBooleanAction;
  36 
  37 import java.io.IOException;
  38 import java.lang.invoke.MethodType;
  39 import java.nio.file.Files;
  40 import java.nio.file.Path;
  41 import java.util.ArrayList;
  42 import java.util.Arrays;

  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";

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

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

 502             }
 503         }



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

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


















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

 794 
 795             mv.visitLabel(L_endBlock);
 796 
 797             // Generate exception handler
 798             mv.visitLabel(L_RuntimeHandler);
 799             mv.visitInsn(ATHROW);   // just rethrow the exception
 800 
 801             mv.visitLabel(L_ThrowableHandler);
 802             mv.visitVarInsn(ASTORE, 1);
 803             mv.visitTypeInsn(Opcodes.NEW, JLR_UNDECLARED_THROWABLE_EX);
 804             mv.visitInsn(DUP);
 805             mv.visitVarInsn(ALOAD, 1);
 806             mv.visitMethodInsn(INVOKESPECIAL, JLR_UNDECLARED_THROWABLE_EX,
 807                     "<init>", "(Ljava/lang/Throwable;)V", false);
 808             mv.visitInsn(ATHROW);
 809             // Maxs computed by ClassWriter.COMPUTE_FRAMES, these arguments ignored
 810             mv.visitMaxs(-1, -1);
 811             mv.visitEnd();
 812         }
 813 






















 814         /**
 815          * Generate code for wrapping an argument of the given type
 816          * whose value can be found at the specified local variable
 817          * index, in order for it to be passed (as an Object) to the
 818          * invocation handler's "invoke" method.
 819          */
 820         private void codeWrapArgument(MethodVisitor mv, Class<?> type, int slot) {
 821             if (type.isPrimitive()) {
 822                 PrimitiveTypeInfo prim = PrimitiveTypeInfo.get(type);
 823 
 824                 mv.visitVarInsn(prim.loadOpcode, slot);
 825                 mv.visitMethodInsn(INVOKESTATIC, prim.wrapperClassName, "valueOf",
 826                         prim.wrapperValueOfDesc, false);
 827             } else {
 828                 mv.visitVarInsn(ALOAD, slot);
 829             }
 830         }
 831 
 832         /**
 833          * Generate code for unwrapping a return value of the given
 834          * type from the invocation handler's "invoke" method (as type
 835          * Object) to its correct type.
 836          */
 837         private void codeUnwrapReturnValue(MethodVisitor mv, Class<?> type) {
 838             if (type.isPrimitive()) {
 839                 PrimitiveTypeInfo prim = PrimitiveTypeInfo.get(type);
 840 
 841                 mv.visitTypeInsn(CHECKCAST, prim.wrapperClassName);
 842                 mv.visitMethodInsn(INVOKEVIRTUAL,
 843                         prim.wrapperClassName,
 844                         prim.unwrapMethodName, prim.unwrapMethodDesc, false);
 845 
 846                 mv.visitInsn(prim.returnOpcode);
 847             } else {
 848                 mv.visitTypeInsn(CHECKCAST, dotToSlash(type.getName()));




 849                 mv.visitInsn(ARETURN);
 850             }
 851         }
 852 
 853         /**
 854          * Generate code for initializing the static field that stores
 855          * the Method object for this proxy method. A class loader is
 856          * anticipated at local variable index 0.
 857          */
 858         private void codeFieldInitialization(MethodVisitor mv, String className) {
 859             codeClassForName(mv, fromClass);
 860 
 861             mv.visitLdcInsn(method.getName());
 862 
 863             emitIconstInsn(mv, parameterTypes.length);
 864 
 865             mv.visitTypeInsn(Opcodes.ANEWARRAY, JL_CLASS);
 866 
 867             // Construct an array with the parameter types mapping primitives to Wrapper types
 868             for (int i = 0; i < parameterTypes.length; i++) {

 880                 mv.visitInsn(Opcodes.AASTORE);
 881             }
 882             // lookup the method
 883             mv.visitMethodInsn(INVOKEVIRTUAL,
 884                     JL_CLASS,
 885                     "getMethod",
 886                     "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;",
 887                     false);
 888 
 889             mv.visitFieldInsn(PUTSTATIC,
 890                     dotToSlash(className),
 891                     methodFieldName, LJLR_METHOD);
 892         }
 893 
 894         /*
 895          * =============== Code Generation Utility Methods ===============
 896          */
 897 
 898         /**
 899          * Generate code to invoke the Class.forName with the name of the given
 900          * class to get its Class object at runtime.  The code is written to
 901          * the supplied stream.  Note that the code generated by this method
 902          * may cause the checked ClassNotFoundException to be thrown. A class
 903          * loader is anticipated at local variable index 0.


 904          */
 905         private void codeClassForName(MethodVisitor mv, Class<?> cl) {
 906             mv.visitLdcInsn(cl.getName());
 907             mv.visitInsn(ICONST_0); // false
 908             mv.visitVarInsn(ALOAD, 0); // classLoader
 909             mv.visitMethodInsn(INVOKESTATIC,
 910                     JL_CLASS,
 911                     "forName",
 912                     "(Ljava/lang/String;Z" + LJL_CLASSLOADER + ")Ljava/lang/Class;",
 913                     false);







 914         }
 915 
 916         /**
 917          * Visit a bytecode for a constant.
 918          *
 919          * @param mv  The MethodVisitor
 920          * @param cst The constant value
 921          */
 922         private void emitIconstInsn(MethodVisitor mv, final int cst) {
 923             if (cst >= -1 && cst <= 5) {
 924                 mv.visitInsn(Opcodes.ICONST_0 + cst);
 925             } else if (cst >= Byte.MIN_VALUE && cst <= Byte.MAX_VALUE) {
 926                 mv.visitIntInsn(Opcodes.BIPUSH, cst);
 927             } else if (cst >= Short.MIN_VALUE && cst <= Short.MAX_VALUE) {
 928                 mv.visitIntInsn(Opcodes.SIPUSH, cst);
 929             } else {
 930                 mv.visitLdcInsn(cst);
 931             }
 932         }
 933 

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

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

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

 822 
 823             mv.visitLabel(L_endBlock);
 824 
 825             // Generate exception handler
 826             mv.visitLabel(L_RuntimeHandler);
 827             mv.visitInsn(ATHROW);   // just rethrow the exception
 828 
 829             mv.visitLabel(L_ThrowableHandler);
 830             mv.visitVarInsn(ASTORE, 1);
 831             mv.visitTypeInsn(Opcodes.NEW, JLR_UNDECLARED_THROWABLE_EX);
 832             mv.visitInsn(DUP);
 833             mv.visitVarInsn(ALOAD, 1);
 834             mv.visitMethodInsn(INVOKESPECIAL, JLR_UNDECLARED_THROWABLE_EX,
 835                     "<init>", "(Ljava/lang/Throwable;)V", false);
 836             mv.visitInsn(ATHROW);
 837             // Maxs computed by ClassWriter.COMPUTE_FRAMES, these arguments ignored
 838             mv.visitMaxs(-1, -1);
 839             mv.visitEnd();
 840         }
 841 
 842         Set<Class<?>> preloadClasses() {
 843             Set<Class<?>> preloadClasses = new HashSet<>();
 844             for (Class<?> type : parameterTypes) {
 845                 if (requiresPreload(type)) {
 846                     preloadClasses.add(type);
 847                 }
 848             }
 849             if (requiresPreload(returnType)) {
 850                 preloadClasses.add(returnType);
 851             }
 852             return preloadClasses;
 853         }
 854 
 855         boolean requiresPreload(Class<?> cls) {
 856             Class<?> c = cls;
 857             while (c.isArray()) {
 858                 c = c.getComponentType();
 859             }
 860             return (c.isValue() && !PrimitiveClass.isPrimitiveClass(c)) ||
 861                     PrimitiveClass.isPrimitiveValueType(c);
 862         }
 863 
 864         /**
 865          * Generate code for wrapping an argument of the given type
 866          * whose value can be found at the specified local variable
 867          * index, in order for it to be passed (as an Object) to the
 868          * invocation handler's "invoke" method.
 869          */
 870         private void codeWrapArgument(MethodVisitor mv, Class<?> type, int slot) {
 871             if (type.isPrimitive()) {
 872                 PrimitiveTypeInfo prim = PrimitiveTypeInfo.get(type);
 873 
 874                 mv.visitVarInsn(prim.loadOpcode, slot);
 875                 mv.visitMethodInsn(INVOKESTATIC, prim.wrapperClassName, "valueOf",
 876                         prim.wrapperValueOfDesc, false);
 877             } else {
 878                 mv.visitVarInsn(ALOAD, slot);
 879             }
 880         }
 881 
 882         /**
 883          * Generate code for unwrapping a return value of the given
 884          * type from the invocation handler's "invoke" method (as type
 885          * Object) to its correct type.
 886          */
 887         private void codeUnwrapReturnValue(MethodVisitor mv, Class<?> type) {
 888             if (type.isPrimitive()) {
 889                 PrimitiveTypeInfo prim = PrimitiveTypeInfo.get(type);
 890 
 891                 mv.visitTypeInsn(CHECKCAST, prim.wrapperClassName);
 892                 mv.visitMethodInsn(INVOKEVIRTUAL,
 893                         prim.wrapperClassName,
 894                         prim.unwrapMethodName, prim.unwrapMethodDesc, false);
 895 
 896                 mv.visitInsn(prim.returnOpcode);
 897             } else {
 898                 String internalName = dotToSlash(type.getName());
 899                 if (PrimitiveClass.isPrimitiveValueType(type)) {
 900                     internalName = 'Q' + internalName + ";";
 901                 }
 902                 mv.visitTypeInsn(CHECKCAST, internalName);
 903                 mv.visitInsn(ARETURN);
 904             }
 905         }
 906 
 907         /**
 908          * Generate code for initializing the static field that stores
 909          * the Method object for this proxy method. A class loader is
 910          * anticipated at local variable index 0.
 911          */
 912         private void codeFieldInitialization(MethodVisitor mv, String className) {
 913             codeClassForName(mv, fromClass);
 914 
 915             mv.visitLdcInsn(method.getName());
 916 
 917             emitIconstInsn(mv, parameterTypes.length);
 918 
 919             mv.visitTypeInsn(Opcodes.ANEWARRAY, JL_CLASS);
 920 
 921             // Construct an array with the parameter types mapping primitives to Wrapper types
 922             for (int i = 0; i < parameterTypes.length; i++) {

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