Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  package org.codehaus.groovy.reflection;
  
  import  org.objectweb.asm.ClassWriter;
  import  org.objectweb.asm.Opcodes;
  import  org.objectweb.asm.MethodVisitor;
  
 
 public class MethodHandleFactory implements Opcodes{
 
     public static MethodHandle unreflect (Method method) {
         if (. != null || checkAccessable(method)) {
           return createCompiledMethodHandle (method, ClassInfo.getClassInfo(method.getDeclaringClass()).getArtifactClassLoader());
         }
 
         return new ReflectiveMethodHandle(method);
     }
 
     private static MethodHandle unreflect (Method methodClassLoaderForClassArtifacts loader) {
         if (. != null || checkAccessable(method))
           return createCompiledMethodHandle (methodloader);
 
         return new ReflectiveMethodHandle(method);
     }
 
     private static boolean checkAccessable(Method method) {
         if (!Modifier.isPublic(method.getDeclaringClass().getModifiers()))
           return false;
 
         if (!Modifier.isPublic(method.getModifiers()))
           return false;
 
         for (Class paramType : method.getParameterTypes())
             if (!Modifier.isPublic(paramType.getModifiers()))
               return false;
 
         return true;
     }
 
     public static void genLoadParameters(int argumentIndex, MethodVisitor mvBytecodeHelper helperMethod method) {
         Class<?>[] parameters = method.getParameterTypes();
         int size = parameters.length;
         for (int i = 0; i < sizei++) {
             // unpack argument from Object[]
             mv.visitVarInsn(Opcodes.ALOAD, argumentIndex);
             helper.pushConstant(i);
             mv.visitInsn(Opcodes.AALOAD);
 
             // cast argument to parameter class, inclusive unboxing
             // for methods with primitive types
             Class type = parameters[i];
             if (type.isPrimitive()) {
                 helper.unbox(type);
             } else {
                 helper.doCast(type);
             }
         }
     }
 
     public static void genLoadParametersDirect(int argumentIndex, MethodVisitor mvBytecodeHelper helperMethod method) {
         Class<?>[] parameters = method.getParameterTypes();
         int size = parameters.length;
         for (int i = 0; i < sizei++) {
             mv.visitVarInsn(Opcodes.ALOAD, argumentIndex+i);
 
             // cast argument to parameter class, inclusive unboxing
             // for methods with primitive types
             Class type = parameters[i];
             if (type.isPrimitive()) {
                 helper.unbox(type);
             } else {
                 helper.doCast(type);
             }
         }
     }
 
     public static void genLoadParametersPrimitiveDirect(int argumentIndex, MethodVisitor mvBytecodeHelper helperMethod method) {
         Class<?>[] parameters = method.getParameterTypes();
         int size = parameters.length;
         int idx = 0;
         for (int i = 0; i < sizei++, idx++) {
             Class type = parameters[i];
             if (type == double.class) {
                 mv.visitVarInsn(DLOAD, idx++);
             } else if (type == float.class) {
                 mv.visitVarInsn(FLOAD, idx);
             } else if (type == long.class) {
                 mv.visitVarInsn(LLOAD, idx++);
             } else if (
                    type == boolean.class
                 || type == char.class
                 || type == byte.class
                 || type == int.class
                 || type == short.class) {
                 mv.visitVarInsn(ILOAD, idx);
             } else {
                mv.visitVarInsn(ALOAD, idx);
                helper.doCast(type);
            }
        }
    }
    private static class ReflectiveMethodHandle extends MethodHandle {
        private final Method method;
        public ReflectiveMethodHandle(Method method) {
            this. = method;
            method.setAccessible(true);
        }
        public Object invoke (Object receiverObject [] argsthrows Throwable{
            return  .invoke(receiverargs);
        }
    }
    private static MethodHandle createCompiledMethodHandle(Method methodClassLoaderForClassArtifacts loader) {
        try {
          Constructor c = compileMethodHandle(methodloader);
          if (c != null)
            return (MethodHandlec.newInstance();
        } catch (Throwable e) { //
        }
        return new ReflectiveMethodHandle(method);
    }
    private static Constructor compileMethodHandle(Method cachedMethodClassLoaderForClassArtifacts loader) {
        ClassWriter cw = new ClassWriter(true);
        final String name = loader.createClassName(cachedMethod);
        final byte[] bytes = genMethodHandle(cachedMethodcwname);
        return loader.defineClassAndGetConstructor(namebytes);
    }
    private static byte[] genMethodHandle(Method method, ClassWriter cwString name) {
        cw.visit(Opcodes.V1_4, Opcodes.ACC_PUBLIC, name.replace('.','/'), null"org/codehaus/groovy/reflection/MethodHandle"null);
        genConstructor(cw"org/codehaus/groovy/reflection/MethodHandle");
        genInvokeXxxWithArray(cwmethod);
        genInvokeWithFixedParams(cwmethod);
        genInvokeWithFixedPrimitiveParams(cwmethod);
        cw.visitEnd();
        return cw.toByteArray();
    }
    private static void genConstructor(ClassWriter cwfinal String superClass) {
        MethodVisitor mv;
        mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>""()V"nullnull);
        mv.visitCode();
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, superClass"<init>""()V");
        mv.visitInsn(Opcodes.RETURN);
        mv.visitMaxs(0, 0);
        mv.visitEnd();
    }
    public static void genInvokeXxxWithArray(ClassWriter cwMethod method) {
        MethodVisitor mv;
        mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "invoke""(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;"null);
        mv.visitCode();
        BytecodeHelper helper = new BytecodeHelper(mv);
        Class callClass = method.getDeclaringClass();
        boolean useInterface = callClass.isInterface();
        String type = BytecodeHelper.getClassInternalName(callClass.getName());
        String descriptor = BytecodeHelper.getMethodDescriptor(method.getReturnType(), method.getParameterTypes());
        // make call
        if (Modifier.isStatic(method.getModifiers())) {
            genLoadParameters(2, mvhelpermethod);
            mv.visitMethodInsn(Opcodes.INVOKESTATIC, typemethod.getName(), descriptor);
        } else {
            mv.visitVarInsn(Opcodes.ALOAD, 1);
            helper.doCast(callClass);
            genLoadParameters(2, mvhelpermethod);
            mv.visitMethodInsn((useInterface) ? Opcodes.INVOKEINTERFACE : Opcodes.INVOKEVIRTUAL, typemethod.getName(), descriptor);
        }
        helper.box(method.getReturnType());
        if (method.getReturnType() == void.class) {
            mv.visitInsn(Opcodes.ACONST_NULL);
        }
        mv.visitInsn(Opcodes.ARETURN);
        mv.visitMaxs(0, 0);
        mv.visitEnd();
    }
    private static void genInvokeWithFixedParams(ClassWriter cwMethod method) {
        MethodVisitor mv;
        final int pc = method.getParameterTypes().length;
        if (pc <= 4)
        {
            StringBuilder pdescb = new StringBuilder();
            for (int i = 0; i != pc; ++i)
              pdescb.append("Ljava/lang/Object;");
            String pdesc = pdescb.toString();
            mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "invoke""(Ljava/lang/Object;" + pdesc + ")Ljava/lang/Object;"null);
            mv.visitCode();
            BytecodeHelper helper = new BytecodeHelper(mv);
            Class callClass = method.getDeclaringClass();
            boolean useInterface = callClass.isInterface();
            String type = BytecodeHelper.getClassInternalName(callClass.getName());
            String descriptor = BytecodeHelper.getMethodDescriptor(method.getReturnType(), method.getParameterTypes());
            // make call
             if (Modifier.isStatic(method.getModifiers())) {
                MethodHandleFactory.genLoadParametersDirect(2, mvhelpermethod);
                mv.visitMethodInsn(Opcodes.INVOKESTATIC, typemethod.getName(), descriptor);
            } else {
                mv.visitVarInsn(Opcodes.ALOAD, 1);
                helper.doCast(callClass);
                MethodHandleFactory.genLoadParametersDirect(2, mvhelpermethod);
                mv.visitMethodInsn((useInterface) ? Opcodes.INVOKEINTERFACE : Opcodes.INVOKEVIRTUAL, typemethod.getName(), descriptor);
            }
            helper.box(method.getReturnType());
            if (method.getReturnType() == void.class) {
                mv.visitInsn(Opcodes.ACONST_NULL);
            }
            mv.visitInsn(Opcodes.ARETURN);
            mv.visitMaxs(0, 0);
            mv.visitEnd();
        }
    }
    private static void genInvokeWithFixedPrimitiveParams(ClassWriter cwMethod method) {
        MethodVisitor mv;
        final Class<?>[] pt = method.getParameterTypes();
        final int pc = pt.length;
        if (pc > 0 && pc <= 3)
        {
            StringBuilder pdescb = new StringBuilder();
            boolean hasPrimitive = false;
            for (int i = 0; i != pc; ++i)
              if (pt[i].isPrimitive()) {
                  hasPrimitive = true;
                  pdescb.append(BytecodeHelper.getTypeDescription(pt[i]));
              }
              else
                pdescb.append("Ljava/lang/Object;");
            if (!hasPrimitive)
              return;
            String pdesc = pdescb.toString();
            mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "invoke""(Ljava/lang/Object;" + pdesc + ")Ljava/lang/Object;"null);
            mv.visitCode();
            BytecodeHelper helper = new BytecodeHelper(mv);
            Class callClass = method.getDeclaringClass();
            boolean useInterface = callClass.isInterface();
            String type = BytecodeHelper.getClassInternalName(callClass.getName());
            String descriptor = BytecodeHelper.getMethodDescriptor(method.getReturnType(), method.getParameterTypes());
            // make call
             if (Modifier.isStatic(method.getModifiers())) {
                MethodHandleFactory.genLoadParametersPrimitiveDirect(2, mvhelpermethod);
                mv.visitMethodInsn(Opcodes.INVOKESTATIC, typemethod.getName(), descriptor);
            } else {
                mv.visitVarInsn(Opcodes.ALOAD, 1);
                helper.doCast(callClass);
                MethodHandleFactory.genLoadParametersPrimitiveDirect(2, mvhelpermethod);
                mv.visitMethodInsn((useInterface) ? Opcodes.INVOKEINTERFACE : Opcodes.INVOKEVIRTUAL, typemethod.getName(), descriptor);
            }
            helper.box(method.getReturnType());
            if (method.getReturnType() == void.class) {
                mv.visitInsn(Opcodes.ACONST_NULL);
            }
            mv.visitInsn(Opcodes.ARETURN);
            mv.visitMaxs(0, 0);
            mv.visitEnd();
        }
    }
    private static final String[] EXCEPTIONS = new String[] { "java/lang/Throwable" };