Search in sources :

Example 16 with ClassWriter

use of org.objectweb.asm.ClassWriter in project android_frameworks_base by DirtyUnicorns.

the class AsmGenerator method transform.

/**
     * Transforms a class.
     * <p/>
     * There are 3 kind of transformations:
     *
     * 1- For "mock" dependencies classes, we want to remove all code from methods and replace
     * by a stub. Native methods must be implemented with this stub too. Abstract methods are
     * left intact. Modified classes must be overridable (non-private, non-final).
     * Native methods must be made non-final, non-private.
     *
     * 2- For "keep" classes, we want to rewrite all native methods as indicated above.
     * If a class has native methods, it must also be made non-private, non-final.
     *
     * Note that unfortunately static methods cannot be changed to non-static (since static and
     * non-static are invoked differently.)
     */
byte[] transform(ClassReader cr, boolean stubNativesOnly) {
    boolean hasNativeMethods = hasNativeMethods(cr);
    // Get the class name, as an internal name (e.g. com/android/SomeClass$InnerClass)
    String className = cr.getClassName();
    String newName = transformName(className);
    // transformName returns its input argument if there's no need to rename the class
    if (!newName.equals(className)) {
        mRenameCount++;
        // This class is being renamed, so remove it from the list of classes not renamed.
        mClassesNotRenamed.remove(className);
    }
    mLog.debug("Transform %s%s%s%s", className, newName.equals(className) ? "" : " (renamed to " + newName + ")", hasNativeMethods ? " -- has natives" : "", stubNativesOnly ? " -- stub natives only" : "");
    // Rewrite the new class from scratch, without reusing the constant pool from the
    // original class reader.
    ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
    ClassVisitor cv = cw;
    // FIXME Generify
    if ("android/content/res/Resources".equals(className)) {
        cv = new FieldInjectorAdapter(cv);
    }
    if (mReplaceMethodCallsClasses.contains(className)) {
        cv = new ReplaceMethodCallsAdapter(cv, className);
    }
    cv = new RefactorClassAdapter(cv, mRefactorClasses);
    if (!newName.equals(className)) {
        cv = new RenameClassAdapter(cv, className, newName);
    }
    String binaryNewName = newName.replace('/', '.');
    if (mInjectedMethodsMap.keySet().contains(binaryNewName)) {
        cv = new InjectMethodsAdapter(cv, mInjectedMethodsMap.get(binaryNewName));
    }
    cv = new TransformClassAdapter(mLog, mStubMethods, mDeleteReturns.get(className), newName, cv, stubNativesOnly);
    Set<String> delegateMethods = mDelegateMethods.get(className);
    if (delegateMethods != null && !delegateMethods.isEmpty()) {
        // known to have no native methods, just skip this step.
        if (hasNativeMethods || !(delegateMethods.size() == 1 && delegateMethods.contains(DelegateClassAdapter.ALL_NATIVES))) {
            cv = new DelegateClassAdapter(mLog, cv, className, delegateMethods);
        }
    }
    Set<String> promoteFields = mPromotedFields.get(className);
    if (promoteFields != null && !promoteFields.isEmpty()) {
        cv = new PromoteFieldClassAdapter(cv, promoteFields);
    }
    cr.accept(cv, 0);
    return cw.toByteArray();
}
Also used : ClassVisitor(org.objectweb.asm.ClassVisitor) ClassWriter(org.objectweb.asm.ClassWriter)

Example 17 with ClassWriter

use of org.objectweb.asm.ClassWriter in project android_frameworks_base by DirtyUnicorns.

the class StubMethodAdapterTest method testBoolean.

/**
     * @param methodPredicate tests if the method should be replaced
     */
private void testBoolean(BiPredicate<String, Type> methodPredicate, Consumer<Boolean> assertion, String methodName) throws Exception {
    ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
    // Always rename the class to avoid conflict with the original class.
    String newClassName = STUB_CLASS_NAME + '_';
    new ClassReader(STUB_CLASS_NAME).accept(new ClassAdapter(newClassName, writer, methodPredicate), 0);
    MyClassLoader myClassLoader = new MyClassLoader(newClassName, writer.toByteArray());
    Class<?> aClass = myClassLoader.loadClass(newClassName);
    assertTrue("StubClass not loaded by the classloader. Likely a bug in the test.", myClassLoader.findClassCalled);
    Method method = aClass.getMethod(methodName);
    Object o = aClass.newInstance();
    assertion.accept((Boolean) method.invoke(o));
}
Also used : ClassReader(org.objectweb.asm.ClassReader) Method(java.lang.reflect.Method) ClassWriter(org.objectweb.asm.ClassWriter)

Example 18 with ClassWriter

use of org.objectweb.asm.ClassWriter in project Minechem by iopleke.

the class MinechemTransformer method injectBytes.

private byte[] injectBytes(Method method, InstructionNode instructionNode, byte[] data) {
    ClassNode classNode = new ClassNode();
    ClassReader classReader = new ClassReader(data);
    classReader.accept(classNode, ClassReader.EXPAND_FRAMES);
    MethodNode methodNode = getMethodByName(classNode, method);
    AbstractInsnNode pos = findInstructionNode(instructionNode, methodNode);
    if (instructionNode.replace) {
        methodNode.instructions.insertBefore(pos, instructionNode.getInsnList());
        methodNode.instructions.remove(pos);
    } else {
        methodNode.instructions.insertBefore(pos, instructionNode.getInsnList());
    }
    ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
    classNode.accept(writer);
    return writer.toByteArray();
}
Also used : ClassNode(org.objectweb.asm.tree.ClassNode) MethodNode(org.objectweb.asm.tree.MethodNode) ClassReader(org.objectweb.asm.ClassReader) AbstractInsnNode(org.objectweb.asm.tree.AbstractInsnNode) ClassWriter(org.objectweb.asm.ClassWriter)

Example 19 with ClassWriter

use of org.objectweb.asm.ClassWriter in project android_frameworks_base by AOSPA.

the class DelegateClassAdapterTest method testDelegateNative.

@Test
public void testDelegateNative() throws Throwable {
    ClassWriter cw = new ClassWriter(0);
    String internalClassName = NATIVE_CLASS_NAME.replace('.', '/');
    HashSet<String> delegateMethods = new HashSet<>();
    delegateMethods.add(DelegateClassAdapter.ALL_NATIVES);
    DelegateClassAdapter cv = new DelegateClassAdapter(mLog, cw, internalClassName, delegateMethods);
    ClassReader cr = new ClassReader(NATIVE_CLASS_NAME);
    cr.accept(cv, 0);
    // Load the generated class in a different class loader and try it
    ClassLoader2 cl2 = null;
    try {
        cl2 = new ClassLoader2() {

            @Override
            public void testModifiedInstance() throws Exception {
                Class<?> clazz2 = loadClass(NATIVE_CLASS_NAME);
                Object i2 = clazz2.newInstance();
                assertNotNull(i2);
                // Use reflection to access inner methods
                assertEquals(42, callAdd(i2, 20, 22));
                Object[] objResult = new Object[] { null };
                int result = callCallNativeInstance(i2, 10, 3.1415, objResult);
                assertEquals((int) (10 + 3.1415), result);
                assertSame(i2, objResult[0]);
                // Check that the native method now has the new annotation and is not native
                Method[] m = clazz2.getDeclaredMethods();
                Method nativeInstanceMethod = null;
                for (Method method : m) {
                    if ("native_instance".equals(method.getName())) {
                        nativeInstanceMethod = method;
                        break;
                    }
                }
                assertNotNull(nativeInstanceMethod);
                assertFalse(Modifier.isNative(nativeInstanceMethod.getModifiers()));
                Annotation[] a = nativeInstanceMethod.getAnnotations();
                assertEquals("LayoutlibDelegate", a[0].annotationType().getSimpleName());
            }
        };
        cl2.add(NATIVE_CLASS_NAME, cw);
        cl2.testModifiedInstance();
    } catch (Throwable t) {
        throw dumpGeneratedClass(t, cl2);
    }
}
Also used : Method(java.lang.reflect.Method) ClassWriter(org.objectweb.asm.ClassWriter) IOException(java.io.IOException) InvocationTargetException(java.lang.reflect.InvocationTargetException) ClassReader(org.objectweb.asm.ClassReader) OuterClass(com.android.tools.layoutlib.create.dataclass.OuterClass) StaticInnerClass(com.android.tools.layoutlib.create.dataclass.OuterClass.StaticInnerClass) InnerClass(com.android.tools.layoutlib.create.dataclass.OuterClass.InnerClass) HashSet(java.util.HashSet) Test(org.junit.Test)

Example 20 with ClassWriter

use of org.objectweb.asm.ClassWriter in project android_frameworks_base by AOSPA.

the class DelegateClassAdapterTest method testNoOp.

/**
     * Tests that a class not being modified still works.
     */
@Test
public void testNoOp() throws Throwable {
    // create an instance of the class that will be modified
    // (load the class in a distinct class loader so that we can trash its definition later)
    ClassLoader cl1 = new ClassLoader(this.getClass().getClassLoader()) {
    };
    @SuppressWarnings("unchecked") Class<ClassWithNative> clazz1 = (Class<ClassWithNative>) cl1.loadClass(NATIVE_CLASS_NAME);
    ClassWithNative instance1 = clazz1.newInstance();
    assertEquals(42, instance1.add(20, 22));
    try {
        instance1.callNativeInstance(10, 3.1415, new Object[0]);
        fail("Test should have failed to invoke callTheNativeMethod [1]");
    } catch (UnsatisfiedLinkError e) {
    // This is expected to fail since the native method is not implemented.
    }
    // Now process it but tell the delegate to not modify any method
    ClassWriter cw = new ClassWriter(0);
    HashSet<String> delegateMethods = new HashSet<>();
    String internalClassName = NATIVE_CLASS_NAME.replace('.', '/');
    DelegateClassAdapter cv = new DelegateClassAdapter(mLog, cw, internalClassName, delegateMethods);
    ClassReader cr = new ClassReader(NATIVE_CLASS_NAME);
    cr.accept(cv, 0);
    // Load the generated class in a different class loader and try it again
    ClassLoader2 cl2 = null;
    try {
        cl2 = new ClassLoader2() {

            @Override
            public void testModifiedInstance() throws Exception {
                Class<?> clazz2 = loadClass(NATIVE_CLASS_NAME);
                Object i2 = clazz2.newInstance();
                assertNotNull(i2);
                assertEquals(42, callAdd(i2, 20, 22));
                try {
                    callCallNativeInstance(i2, 10, 3.1415, new Object[0]);
                    fail("Test should have failed to invoke callTheNativeMethod [2]");
                } catch (InvocationTargetException e) {
                    // This is expected to fail since the native method has NOT been
                    // overridden here.
                    assertEquals(UnsatisfiedLinkError.class, e.getCause().getClass());
                }
                // Check that the native method does NOT have the new annotation
                Method[] m = clazz2.getDeclaredMethods();
                Method nativeInstanceMethod = null;
                for (Method method : m) {
                    if ("native_instance".equals(method.getName())) {
                        nativeInstanceMethod = method;
                        break;
                    }
                }
                assertNotNull(nativeInstanceMethod);
                assertTrue(Modifier.isNative(nativeInstanceMethod.getModifiers()));
                Annotation[] a = nativeInstanceMethod.getAnnotations();
                assertEquals(0, a.length);
            }
        };
        cl2.add(NATIVE_CLASS_NAME, cw);
        cl2.testModifiedInstance();
    } catch (Throwable t) {
        throw dumpGeneratedClass(t, cl2);
    }
}
Also used : Method(java.lang.reflect.Method) ClassWriter(org.objectweb.asm.ClassWriter) IOException(java.io.IOException) InvocationTargetException(java.lang.reflect.InvocationTargetException) InvocationTargetException(java.lang.reflect.InvocationTargetException) ClassReader(org.objectweb.asm.ClassReader) OuterClass(com.android.tools.layoutlib.create.dataclass.OuterClass) StaticInnerClass(com.android.tools.layoutlib.create.dataclass.OuterClass.StaticInnerClass) InnerClass(com.android.tools.layoutlib.create.dataclass.OuterClass.InnerClass) ClassWithNative(com.android.tools.layoutlib.create.dataclass.ClassWithNative) HashSet(java.util.HashSet) Test(org.junit.Test)

Aggregations

ClassWriter (org.objectweb.asm.ClassWriter)471 ClassReader (org.objectweb.asm.ClassReader)275 MethodVisitor (org.objectweb.asm.MethodVisitor)115 Test (org.junit.Test)94 ClassVisitor (org.objectweb.asm.ClassVisitor)82 ClassNode (org.objectweb.asm.tree.ClassNode)70 IOException (java.io.IOException)57 SemanticVersioningClassVisitor (org.apache.aries.versioning.utils.SemanticVersioningClassVisitor)52 Label (org.objectweb.asm.Label)51 HashSet (java.util.HashSet)37 Method (java.lang.reflect.Method)36 BinaryCompatibilityStatus (org.apache.aries.versioning.utils.BinaryCompatibilityStatus)32 Type (org.objectweb.asm.Type)30 File (java.io.File)27 InvocationTargetException (java.lang.reflect.InvocationTargetException)27 FieldVisitor (org.objectweb.asm.FieldVisitor)26 InputStream (java.io.InputStream)25 MethodNode (org.objectweb.asm.tree.MethodNode)25 OuterClass (com.android.tools.layoutlib.create.dataclass.OuterClass)23 InnerClass (com.android.tools.layoutlib.create.dataclass.OuterClass.InnerClass)23