Search in sources :

Example 71 with Method

use of org.objectweb.asm.commons.Method in project robolectric by robolectric.

the class ClassInstrumentor method generateStaticInitializerNotifierMethod.

private static MethodNode generateStaticInitializerNotifierMethod(MutableClass mutableClass) {
    MethodNode methodNode = new MethodNode(Opcodes.ACC_STATIC, "<clinit>", "()V", "()V", null);
    RobolectricGeneratorAdapter generator = new RobolectricGeneratorAdapter(methodNode);
    generator.push(mutableClass.classType);
    generator.invokeStatic(Type.getType(RobolectricInternals.class), new Method("classInitializing", "(Ljava/lang/Class;)V"));
    generator.returnValue();
    generator.endMethod();
    return methodNode;
}
Also used : MethodNode(org.objectweb.asm.tree.MethodNode) Method(org.objectweb.asm.commons.Method)

Example 72 with Method

use of org.objectweb.asm.commons.Method in project robolectric by robolectric.

the class ProxyMaker method createProxyFactory.

<T> Factory createProxyFactory(Class<T> targetClass) {
    Type targetType = Type.getType(targetClass);
    String targetName = targetType.getInternalName();
    String proxyName = targetName + "$GeneratedProxy";
    Type proxyType = Type.getType("L" + proxyName.replace('.', '/') + ";");
    ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
    writer.visit(V1_7, ACC_PUBLIC | ACC_SYNTHETIC | ACC_SUPER | ACC_FINAL, proxyName, null, targetName, null);
    writer.visitField(ACC_PUBLIC | ACC_SYNTHETIC, TARGET_FIELD, targetType.getDescriptor(), null, null);
    for (java.lang.reflect.Method method : targetClass.getMethods()) {
        if (!shouldProxy(method))
            continue;
        Method proxyMethod = Method.getMethod(method);
        GeneratorAdapter m = new GeneratorAdapter(ACC_PUBLIC | ACC_SYNTHETIC, Method.getMethod(method), null, null, writer);
        m.loadThis();
        m.getField(proxyType, TARGET_FIELD, targetType);
        m.loadArgs();
        String targetMethod = methodMapper.getName(targetClass.getName(), method.getName());
        // In Java 8 we could use invokespecial here but not in 7, from jvm spec:
        // If an invokespecial instruction names a method which is not an instance
        // initialization method, then the type of the target reference on the operand
        // stack must be assignment compatible with the current class (JLS ยง5.2).
        m.visitMethodInsn(INVOKEVIRTUAL, targetName, targetMethod, proxyMethod.getDescriptor(), false);
        m.returnValue();
        m.endMethod();
    }
    writer.visitEnd();
    byte[] bytecode = writer.toByteArray();
    if (DEBUG) {
        File file = new File("/tmp", targetClass.getCanonicalName() + "-DirectProxy.class");
        System.out.println("Generated Direct Proxy: " + file.getAbsolutePath());
        try (OutputStream out = new FileOutputStream(file)) {
            out.write(bytecode);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    final Class<?> proxyClass = UNSAFE.defineAnonymousClass(targetClass, bytecode, null);
    try {
        final Field field = proxyClass.getDeclaredField(TARGET_FIELD);
        return new Factory() {

            @Override
            public <E> E createProxy(Class<E> targetClass, E target) {
                try {
                    Object proxy = UNSAFE.allocateInstance(proxyClass);
                    field.set(proxy, target);
                    return targetClass.cast(proxy);
                } catch (Throwable t) {
                    throw new AssertionError(t);
                }
            }
        };
    } catch (NoSuchFieldException e) {
        throw new AssertionError(e);
    }
}
Also used : OutputStream(java.io.OutputStream) FileOutputStream(java.io.FileOutputStream) Method(org.objectweb.asm.commons.Method) IOException(java.io.IOException) ClassWriter(org.objectweb.asm.ClassWriter) Field(java.lang.reflect.Field) Type(org.objectweb.asm.Type) FileOutputStream(java.io.FileOutputStream) GeneratorAdapter(org.objectweb.asm.commons.GeneratorAdapter) File(java.io.File)

Example 73 with Method

use of org.objectweb.asm.commons.Method in project eclipse.themes.darker by jinmingjian.

the class DarkerWeavingHook method transform.

public void transform(WovenClass wovenClass) {
    byte[] bytes = wovenClass.getBytes();
    ClassReader cr = new ClassReader(bytes);
    ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
    cr.accept(cw, 0);
    Method md = Method.getMethod("org.eclipse.swt.graphics.Color getForeground ()");
    MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, md.getName(), md.getDescriptor(), null, null);
    final GeneratorAdapter mg = new GeneratorAdapter(ACC_PUBLIC, md, mv);
    final Label LABEL_SKIP_CALL_TO_SUPER = new Label();
    final Label LABEL_LOOP_CMP = new Label();
    final Label LABEL_LOOP_START = new Label();
    mg.newInstance(Type.getType(Exception.class));
    mg.dup();
    mg.invokeConstructor(Type.getType(Exception.class), Method.getMethod("void <init> ()"));
    mg.invokeVirtual(Type.getType(Exception.class), Method.getMethod("StackTraceElement[] getStackTrace ()"));
    mg.storeLocal(1, Type.getType(StackTraceElement[].class));
    mg.push(10);
    mg.storeLocal(2, Type.getType(int.class));
    mg.goTo(LABEL_LOOP_CMP);
    mg.mark(LABEL_LOOP_START);
    mg.loadLocal(1);
    mg.loadLocal(2);
    mg.arrayLoad(Type.getType(StackTraceElement.class));
    mg.invokeVirtual(Type.getType(StackTraceElement.class), Method.getMethod("String getClassName ()"));
    mg.push("Dialog");
    mg.invokeVirtual(Type.getType(String.class), Method.getMethod("int indexOf (String)"));
    mg.push(-1);
    mg.ifICmp(GeneratorAdapter.EQ, LABEL_SKIP_CALL_TO_SUPER);
    // //XXX: DEBUG
    // mg.getStatic(Type.getType(System.class), "out", Type.getType(java.io.PrintStream.class));
    // mg.push("2");
    // mg.invokeVirtual(Type.getType(java.io.PrintStream.class), Method.getMethod("void println (String)"));
    // //XXX: DEBUG
    mg.loadThis();
    mg.invokeConstructor(Type.getType("Lorg/eclipse/swt/widgets/Control;"), Method.getMethod("org.eclipse.swt.graphics.Color getForeground ()"));
    mg.returnValue();
    mg.mark(LABEL_SKIP_CALL_TO_SUPER);
    mg.iinc(2, 1);
    mg.mark(LABEL_LOOP_CMP);
    mg.loadLocal(2);
    mg.loadLocal(1);
    mg.arrayLength();
    mg.ifICmp(GeneratorAdapter.LT, LABEL_LOOP_START);
    mg.loadThis();
    mg.invokeVirtual(Type.getType("Lorg/eclipse/swt/custom/CLabel;"), Method.getMethod("org.eclipse.swt.widgets.Display getDisplay ()"));
    mg.push(1);
    mg.invokeVirtual(Type.getType("Lorg/eclipse/swt/widgets/Display;"), Method.getMethod("org.eclipse.swt.graphics.Color getSystemColor (int)"));
    mg.returnValue();
    mg.endMethod();
    cw.visitEnd();
    wovenClass.setBytes(cw.toByteArray());
}
Also used : Label(org.objectweb.asm.Label) ClassReader(org.objectweb.asm.ClassReader) GeneratorAdapter(org.objectweb.asm.commons.GeneratorAdapter) Method(org.objectweb.asm.commons.Method) ClassWriter(org.objectweb.asm.ClassWriter) IOException(java.io.IOException) MethodVisitor(org.objectweb.asm.MethodVisitor)

Example 74 with Method

use of org.objectweb.asm.commons.Method in project aries by apache.

the class ProxySubclassAdapter method visit.

/*
   * This method visits the class to generate the new subclass.
   * 
   * The following things happen here: 1. The class is renamed to a dynamic
   * name 2. The existing class name is changed to be the superclass name so
   * that the generated class extends the original class. 3. A private field
   * is added to store an invocation handler 4. A constructor is added that
   * takes an invocation handler as an argument 5. The constructor method
   * instantiates an instance of the superclass 6. The constructor method sets
   * the invocation handler so the invoke method can be called from all the
   * subsequently rewritten methods 7. Add a getInvocationHandler() method 8.
   * store a static Class object of the superclass so we can reflectively find
   * methods later
   */
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
    LOGGER.debug(Constants.LOG_ENTRY, "visit", new Object[] { version, access, name, signature, superName, interfaces });
    // store the superclass binary name
    this.superclassBinaryName = name.replaceAll("/", "\\.");
    try {
        this.superclassClass = Class.forName(superclassBinaryName, false, loader);
    } catch (ClassNotFoundException cnfe) {
        throw new TypeNotPresentException(superclassBinaryName, cnfe);
    }
    // from the superclass anyway
    if ((access & ACC_ABSTRACT) != 0) {
        // If the super was abstract the subclass should not be!
        access &= ~ACC_ABSTRACT;
    }
    cv.visit(ProxyUtils.getWeavingJavaVersion(), access, newClassName, signature, name, null);
    // add a private field for the invocation handler
    // this isn't static in case we have multiple instances of the same
    // proxy
    cv.visitField(ACC_PRIVATE, IH_FIELD, Type.getDescriptor(InvocationHandler.class), null, null);
    // create a static adapter for generating a static initialiser method in
    // the generated subclass
    staticAdapter = new GeneratorAdapter(ACC_STATIC, new Method("<clinit>", Type.VOID_TYPE, NO_ARGS), null, null, cv);
    // add a zero args constructor method
    Method m = new Method("<init>", Type.VOID_TYPE, NO_ARGS);
    GeneratorAdapter methodAdapter = new GeneratorAdapter(ACC_PUBLIC, m, null, null, cv);
    // loadthis
    methodAdapter.loadThis();
    // List the constructors in the superclass.
    Constructor<?>[] constructors = superclassClass.getDeclaredConstructors();
    // Check that we've got at least one constructor, and get the 1st one in the list.
    if (constructors.length > 0) {
        // We now need to construct the proxy class as though it is going to invoke the superclasses constructor.
        // We do this because we can no longer call the java.lang.Object() zero arg constructor as the JVM now throws a VerifyError.
        // So what we do is build up the calling of the superclasses constructor using nulls and default values. This means that the
        // class bytes can be verified by the JVM, and then in the ProxySubclassGenerator, we load the class without invoking the
        // constructor.
        Method constructor = Method.getMethod(constructors[0]);
        Type[] argTypes = constructor.getArgumentTypes();
        if (argTypes.length == 0) {
            methodAdapter.invokeConstructor(Type.getType(superclassClass), new Method("<init>", Type.VOID_TYPE, NO_ARGS));
        } else {
            for (Type type : argTypes) {
                switch(type.getSort()) {
                    case Type.ARRAY:
                        // We need to process any array or multidimentional arrays.
                        String elementDesc = type.getElementType().getDescriptor();
                        String typeDesc = type.getDescriptor();
                        // Iterate over the number of arrays and load 0 for each one. Keep a count of the number of
                        // arrays as we will need to run different code fo multi dimentional arrays.
                        int index = 0;
                        while (!elementDesc.equals(typeDesc)) {
                            typeDesc = typeDesc.substring(1);
                            methodAdapter.visitInsn(Opcodes.ICONST_0);
                            index++;
                        }
                        // If we're just a single array, then call the newArray method, otherwise use the MultiANewArray instruction.
                        if (index == 1) {
                            methodAdapter.newArray(type.getElementType());
                        } else {
                            methodAdapter.visitMultiANewArrayInsn(type.getDescriptor(), index);
                        }
                        break;
                    case Type.BOOLEAN:
                        methodAdapter.push(true);
                        break;
                    case Type.BYTE:
                        methodAdapter.push(Type.VOID_TYPE);
                        break;
                    case Type.CHAR:
                        methodAdapter.push(Type.VOID_TYPE);
                        break;
                    case Type.DOUBLE:
                        methodAdapter.push(0.0);
                        break;
                    case Type.FLOAT:
                        methodAdapter.push(0.0f);
                        break;
                    case Type.INT:
                        methodAdapter.push(0);
                        break;
                    case Type.LONG:
                        methodAdapter.push(0l);
                        break;
                    case Type.SHORT:
                        methodAdapter.push(0);
                        break;
                    default:
                    case Type.OBJECT:
                        methodAdapter.visitInsn(Opcodes.ACONST_NULL);
                        break;
                }
            }
            methodAdapter.invokeConstructor(Type.getType(superclassClass), new Method("<init>", Type.VOID_TYPE, argTypes));
        }
    }
    methodAdapter.returnValue();
    methodAdapter.endMethod();
    // add a method for getting the invocation handler
    Method setter = new Method("setInvocationHandler", Type.VOID_TYPE, new Type[] { IH_TYPE });
    m = new Method("getInvocationHandler", IH_TYPE, NO_ARGS);
    methodAdapter = new GeneratorAdapter(ACC_PUBLIC | ACC_FINAL, m, null, null, cv);
    // load this to get the field
    methodAdapter.loadThis();
    // get the ih field and return
    methodAdapter.getField(newClassType, IH_FIELD, IH_TYPE);
    methodAdapter.returnValue();
    methodAdapter.endMethod();
    // add a method for setting the invocation handler
    methodAdapter = new GeneratorAdapter(ACC_PUBLIC | ACC_FINAL, setter, null, null, cv);
    // load this to put the field
    methodAdapter.loadThis();
    // load the method arguments (i.e. the invocation handler) to the stack
    methodAdapter.loadArgs();
    // set the ih field using the method argument
    methodAdapter.putField(newClassType, IH_FIELD, IH_TYPE);
    methodAdapter.returnValue();
    methodAdapter.endMethod();
    // loop through the class hierarchy to get any needed methods off the
    // supertypes
    // start by finding the methods declared on the class of interest (the
    // superclass of our dynamic subclass)
    java.lang.reflect.Method[] observedMethods = superclassClass.getDeclaredMethods();
    // add the methods to a set of observedMethods
    ProxySubclassMethodHashSet<String> setOfObservedMethods = new ProxySubclassMethodHashSet<String>(observedMethods.length);
    setOfObservedMethods.addMethodArray(observedMethods);
    // get the next superclass in the hierarchy
    Class<?> nextSuperClass = superclassClass.getSuperclass();
    while (nextSuperClass != null) {
        // set the fields for the current class
        setCurrentAnalysisClassFields(nextSuperClass);
        // add a static field and static initializer code to the generated
        // subclass
        // for each of the superclasses in the hierarchy
        addClassStaticField(currentlyAnalysedClassName);
        LOGGER.debug("Class currently being analysed: {} {}", currentlyAnalysedClassName, currentlyAnalysedClass);
        // now find the methods declared on the current class and add them
        // to a set of foundMethods
        java.lang.reflect.Method[] foundMethods = currentlyAnalysedClass.getDeclaredMethods();
        ProxySubclassMethodHashSet<String> setOfFoundMethods = new ProxySubclassMethodHashSet<String>(foundMethods.length);
        setOfFoundMethods.addMethodArray(foundMethods);
        // remove from the set of foundMethods any methods we saw on a
        // subclass
        // because we want to use the lowest level declaration of a method
        setOfFoundMethods.removeAll(setOfObservedMethods);
        try {
            // read the current class and use a
            // ProxySubclassHierarchyAdapter
            // to process only methods on that class that are in the list
            ClassLoader loader = currentlyAnalysedClass.getClassLoader();
            if (loader == null) {
                loader = this.loader;
            }
            InputStream is = loader.getResourceAsStream(currentlyAnalysedClass.getName().replaceAll("\\.", "/") + ".class");
            if (is == null) {
                // use SystemModuleClassLoader as fallback
                ClassLoader classLoader = new SystemModuleClassLoader();
                is = classLoader.getResourceAsStream(currentlyAnalysedClass.getName().replaceAll("\\.", "/") + ".class");
            }
            ClassReader cr = new ClassReader(is);
            ClassVisitor hierarchyAdapter = new ProxySubclassHierarchyAdapter(this, setOfFoundMethods);
            cr.accept(hierarchyAdapter, ClassReader.SKIP_DEBUG);
        } catch (IOException e) {
            throw new TypeNotPresentException(currentlyAnalysedClassName, e);
        }
        // now add the foundMethods to the overall list of observed methods
        setOfObservedMethods.addAll(setOfFoundMethods);
        // get the next class up in the hierarchy and go again
        nextSuperClass = currentlyAnalysedClass.getSuperclass();
    }
    // we've finished looking at the superclass hierarchy
    // set the fields for the immediate superclass of our dynamic subclass
    setCurrentAnalysisClassFields(superclassClass);
    // add the class static field
    addClassStaticField(currentlyAnalysedClassName);
    // we do the lowest class last because we are already visiting the class
    // when in this adapter code
    // now we are ready to visit all the methods on the lowest class
    // which will happen by the ASM ClassVisitor implemented in this adapter
    LOGGER.debug(Constants.LOG_EXIT, "visit");
}
Also used : Constructor(java.lang.reflect.Constructor) InputStream(java.io.InputStream) Method(org.objectweb.asm.commons.Method) ClassVisitor(org.objectweb.asm.ClassVisitor) IOException(java.io.IOException) InvocationHandler(java.lang.reflect.InvocationHandler) Type(org.objectweb.asm.Type) SystemModuleClassLoader(org.apache.aries.proxy.impl.SystemModuleClassLoader) GeneratorAdapter(org.objectweb.asm.commons.GeneratorAdapter) SystemModuleClassLoader(org.apache.aries.proxy.impl.SystemModuleClassLoader) ClassReader(org.objectweb.asm.ClassReader)

Example 75 with Method

use of org.objectweb.asm.commons.Method in project aries by apache.

the class AbstractWovenProxyMethodAdapter method writeDispatcher.

/**
 * Write out the bytecode instructions necessary to do the dispatch.
 * We know the dispatcher is non-null, and we need a try/catch around the
 * invocation and listener calls.
 */
protected final void writeDispatcher() {
    // Setup locals we will use in the dispatch
    setupLocals();
    // Write the try catch block
    visitTryCatchBlock(beginTry, endTry, endTry, THROWABLE_INAME);
    mark(beginTry);
    // Start dispatching, get the target object and store it
    loadThis();
    getField(typeBeingWoven, DISPATCHER_FIELD, DISPATCHER_TYPE);
    invokeInterface(DISPATCHER_TYPE, new Method("call", OBJECT_TYPE, NO_ARGS));
    storeLocal(dispatchTarget);
    // Pre-invoke, invoke, post-invoke, return
    writePreInvoke();
    // Start the real method
    push(true);
    storeLocal(inNormalMethod);
    // Dispatch the method and store the result (null for void)
    loadLocal(dispatchTarget);
    checkCast(methodDeclaringType);
    loadArgs();
    if (isMethodDeclaringTypeInterface) {
        invokeInterface(methodDeclaringType, currentTransformMethod);
    } else {
        invokeVirtual(methodDeclaringType, currentTransformMethod);
    }
    if (isVoid) {
        visitInsn(ACONST_NULL);
    }
    storeLocal(normalResult);
    // finish the real method and post-invoke
    push(false);
    storeLocal(inNormalMethod);
    writePostInvoke();
    // Return, with the return value if necessary
    if (!!!isVoid) {
        loadLocal(normalResult);
    }
    returnValue();
    // End of our try, start of our catch
    mark(endTry);
    writeMethodCatchHandler();
}
Also used : Method(org.objectweb.asm.commons.Method)

Aggregations

Method (org.objectweb.asm.commons.Method)78 GeneratorAdapter (org.objectweb.asm.commons.GeneratorAdapter)58 Type (org.objectweb.asm.Type)38 ClassWriter (org.objectweb.asm.ClassWriter)14 Label (org.objectweb.asm.Label)14 MethodVisitor (org.objectweb.asm.MethodVisitor)9 IOException (java.io.IOException)7 ClassReader (org.objectweb.asm.ClassReader)7 TypeInfo (com.google.template.soy.jbcsrc.restricted.TypeInfo)6 MethodNode (org.objectweb.asm.tree.MethodNode)6 ExprString (lucee.transformer.expression.ExprString)5 LitString (lucee.transformer.expression.literal.LitString)5 ClassVisitor (org.objectweb.asm.ClassVisitor)5 Schema (co.cask.cdap.api.data.schema.Schema)4 ArrayList (java.util.ArrayList)4 File (java.io.File)3 Set (java.util.Set)3 Nullable (javax.annotation.Nullable)3 ExprDouble (lucee.transformer.expression.ExprDouble)3 MetricsContext (co.cask.cdap.api.metrics.MetricsContext)2