Search in sources :

Example 11 with ClassFile

use of javassist.bytecode.ClassFile in project fakereplace by fakereplace.

the class MethodReplacementTransformer method generateProxyInvocationBytecode.

private static String generateProxyInvocationBytecode(MethodInfo mInfo, int methodNumber, String className, ClassLoader loader, boolean staticMethod, boolean isInterface) throws BadBytecode {
    String proxyName = ProxyDefinitionStore.getProxyName();
    ClassFile proxy = new ClassFile(false, proxyName, "java.lang.Object");
    proxy.setVersionToJava5();
    proxy.setAccessFlags(AccessFlag.PUBLIC);
    // now generate our proxy that is used to actually call the method
    // we use a proxy because it makes the re-writing of loaded classes
    // much simpler
    MethodInfo nInfo;
    if (staticMethod) {
        nInfo = new MethodInfo(proxy.getConstPool(), mInfo.getName(), mInfo.getDescriptor());
    } else {
        // the descriptor is different as now there is an extra parameter for a
        // static call
        String nDesc = "(" + DescriptorUtils.extToInt(className) + mInfo.getDescriptor().substring(1);
        nInfo = new MethodInfo(proxy.getConstPool(), mInfo.getName(), nDesc);
    }
    copyMethodAttributes(mInfo, nInfo);
    // set the sync bit on the proxy if it was set on the method
    nInfo.setAccessFlags(AccessFlag.PUBLIC | AccessFlag.STATIC);
    Bytecode proxyBytecode = new Bytecode(proxy.getConstPool());
    int paramOffset = 0;
    // onto the stack
    if (!staticMethod) {
        proxyBytecode.addAload(0);
        paramOffset = 1;
    }
    // stick the method number in the const pool then load it onto the
    // stack
    int scind = proxy.getConstPool().addIntegerInfo(methodNumber);
    proxyBytecode.addLdc(scind);
    String[] types = DescriptorUtils.descriptorStringToParameterArray(mInfo.getDescriptor());
    // create a new array the same size as the parameter array
    int index = proxyBytecode.getConstPool().addIntegerInfo(types.length);
    proxyBytecode.addLdc(index);
    // create new array to use to pass our parameters
    proxyBytecode.addAnewarray("java.lang.Object");
    int locals = types.length + paramOffset;
    for (int i = 0; i < types.length; ++i) {
        // duplicate the array reference on the stack
        proxyBytecode.add(Opcode.DUP);
        // load the array index into the stack
        index = proxyBytecode.getConstPool().addIntegerInfo(i);
        proxyBytecode.addLdc(index);
        char tp = types[i].charAt(0);
        if (tp != 'L' && tp != '[') {
            // we have a primitive type
            switch(tp) {
                case 'J':
                    proxyBytecode.addLload(i + paramOffset);
                    locals++;
                    break;
                case 'D':
                    proxyBytecode.addDload(i + paramOffset);
                    locals++;
                    break;
                case 'F':
                    proxyBytecode.addFload(i + paramOffset);
                    break;
                default:
                    proxyBytecode.addIload(i + paramOffset);
            }
            // lets box it
            Boxing.box(proxyBytecode, tp);
        } else {
            // load parameter i onto
            proxyBytecode.addAload(i + paramOffset);
        // the stack
        }
        // store the value in the array
        proxyBytecode.add(Opcode.AASTORE);
    }
    // invoke the added static method
    if (staticMethod) {
        proxyBytecode.addInvokestatic(className, Constants.ADDED_STATIC_METHOD_NAME, "(I[Ljava/lang/Object;)Ljava/lang/Object;");
    } else if (isInterface) {
        proxyBytecode.addInvokeinterface(className, Constants.ADDED_METHOD_NAME, "(I[Ljava/lang/Object;)Ljava/lang/Object;", 3);
    } else {
        proxyBytecode.addInvokevirtual(className, Constants.ADDED_METHOD_NAME, "(I[Ljava/lang/Object;)Ljava/lang/Object;");
    }
    // cast it to the appropriate type and return it
    ManipulationUtils.MethodReturnRewriter.addReturnProxyMethod(mInfo.getDescriptor(), proxyBytecode);
    CodeAttribute ca = proxyBytecode.toCodeAttribute();
    ca.setMaxLocals(locals);
    ca.computeMaxStack();
    nInfo.setCodeAttribute(ca);
    // this is so that we do not need to instrument the reflection API to much
    if (!staticMethod) {
        // as this method is never called the bytecode just returns
        MethodInfo method = new MethodInfo(proxy.getConstPool(), mInfo.getName(), mInfo.getDescriptor());
        method.setAccessFlags(mInfo.getAccessFlags());
        if ((method.getAccessFlags() & AccessFlag.ABSTRACT) == 0) {
            Bytecode b = new Bytecode(proxy.getConstPool());
            String ret = DescriptorUtils.getReturnType(mInfo.getDescriptor());
            if (ret.length() == 1) {
                switch(ret) {
                    case "V":
                        b.add(Opcode.RETURN);
                        break;
                    case "D":
                        b.add(Opcode.DCONST_0);
                        b.add(Opcode.DRETURN);
                        break;
                    case "F":
                        b.add(Opcode.FCONST_0);
                        b.add(Opcode.FRETURN);
                        break;
                    case "J":
                        b.add(Opcode.LCONST_0);
                        b.add(Opcode.LRETURN);
                        break;
                    default:
                        b.add(Opcode.ICONST_0);
                        b.add(Opcode.IRETURN);
                        break;
                }
            } else {
                b.add(Opcode.ACONST_NULL);
                b.add(Opcode.ARETURN);
            }
            method.setCodeAttribute(b.toCodeAttribute());
            method.getCodeAttribute().computeMaxStack();
            method.getCodeAttribute().setMaxLocals(locals);
        }
        copyMethodAttributes(mInfo, method);
        try {
            proxy.addMethod(method);
        } catch (DuplicateMemberException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    try {
        proxy.addMethod(nInfo);
    } catch (DuplicateMemberException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    try {
        ByteArrayOutputStream bytes = new ByteArrayOutputStream();
        DataOutputStream dos = new DataOutputStream(bytes);
        proxy.write(dos);
        ProxyDefinitionStore.saveProxyDefinition(loader, proxyName, bytes.toByteArray());
        return proxyName;
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}
Also used : DuplicateMemberException(javassist.bytecode.DuplicateMemberException) ClassFile(javassist.bytecode.ClassFile) DataOutputStream(java.io.DataOutputStream) ByteArrayOutputStream(java.io.ByteArrayOutputStream) IOException(java.io.IOException) CodeAttribute(javassist.bytecode.CodeAttribute) MethodInfo(javassist.bytecode.MethodInfo) BadBytecode(javassist.bytecode.BadBytecode) Bytecode(javassist.bytecode.Bytecode)

Example 12 with ClassFile

use of javassist.bytecode.ClassFile in project fakereplace by fakereplace.

the class Fakereplace method redefine.

public static void redefine(ClassDefinition[] classes, AddedClass[] addedData, boolean wait) {
    try {
        for (AddedClass i : addedData) {
            ClassFile cf = new ClassFile(new DataInputStream(new ByteArrayInputStream(i.getData())));
            mainTransformer.addNewClass(new NewClassData(i.getClassName(), i.getLoader(), cf));
        }
        for (ClassDefinition i : classes) {
            ClassDataStore.instance().markClassReplaced(i.getDefinitionClass());
            BaseClassData baseClassData = ClassDataStore.instance().getBaseClassData(i.getDefinitionClass().getClassLoader(), i.getDefinitionClass().getName());
            if (baseClassData != null) {
                ClassDataStore.instance().saveClassData(i.getDefinitionClass().getClassLoader(), i.getDefinitionClass().getName(), new ClassDataBuilder(baseClassData));
            }
        }
        for (AddedClass c : addedData) {
            ClassLookupManager.addClassInfo(c.getClassName(), c.getLoader(), c.getData());
        }
        inst.redefineClasses(classes);
        clearJvmCaches();
        if (wait) {
            mainTransformer.waitForTasks();
        }
    } catch (Throwable e) {
        try {
            // dump the classes to /tmp so we can look at them
            for (ClassDefinition d : classes) {
                try {
                    ByteArrayInputStream bin = new ByteArrayInputStream(d.getDefinitionClassFile());
                    DataInputStream dis = new DataInputStream(bin);
                    final ClassFile file = new ClassFile(dis);
                    Transformer.getManipulator().transformClass(file, d.getDefinitionClass().getClassLoader(), true, new HashSet<>());
                    String dumpDir = AgentOptions.getOption(AgentOption.DUMP_DIR);
                    if (dumpDir != null) {
                        FileOutputStream s = new FileOutputStream(dumpDir + '/' + d.getDefinitionClass().getName() + "1.class");
                        DataOutputStream dos = new DataOutputStream(s);
                        file.write(dos);
                        dos.flush();
                        dos.close();
                        // s.write(d.getDefinitionClassFile());
                        s.close();
                    }
                } catch (IOException a) {
                    a.printStackTrace();
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        throw (new RuntimeException(e));
    }
}
Also used : ClassFile(javassist.bytecode.ClassFile) DataOutputStream(java.io.DataOutputStream) AddedClass(org.fakereplace.replacement.AddedClass) IOException(java.io.IOException) DataInputStream(java.io.DataInputStream) ClassDefinition(java.lang.instrument.ClassDefinition) ClassDataBuilder(org.fakereplace.data.ClassDataBuilder) IOException(java.io.IOException) UnmodifiableClassException(java.lang.instrument.UnmodifiableClassException) BaseClassData(org.fakereplace.data.BaseClassData) ByteArrayInputStream(java.io.ByteArrayInputStream) NewClassData(org.fakereplace.api.NewClassData) FileOutputStream(java.io.FileOutputStream) HashSet(java.util.HashSet)

Example 13 with ClassFile

use of javassist.bytecode.ClassFile in project compss by bsc-wdc.

the class AddOrchestration method main.

public static void main(String[] args) throws NotFoundException, NameNotFoundException, CannotCompileException, IOException {
    if (args.length < 2) {
        ErrorManager.fatal("Error: missing arguments for loader");
    }
    String className = args[0];
    String classPackage = getPackage(className);
    // Pool creation
    ClassPool pool = ClassPool.getDefault();
    if (classPackage != null && classPackage.trim().length() > 0) {
        pool.importPackage(classPackage);
    }
    // Extracting the class
    CtClass cc = pool.getCtClass(className);
    ClassFile ccFile = cc.getClassFile();
    ConstPool constpool = ccFile.getConstPool();
    for (int i = 1; i < args.length; i++) {
        String methodLabel = args[i];
        String methodName = getMethodName(methodLabel);
        CtClass[] params = getParamClasses(methodLabel, pool);
        CtMethod methodDescriptor = cc.getDeclaredMethod(methodName, params);
        AnnotationsAttribute attr = (AnnotationsAttribute) methodDescriptor.getMethodInfo().getAttribute(AnnotationsAttribute.visibleTag);
        if (attr == null) {
            // Create the annotation
            attr = new AnnotationsAttribute(constpool, AnnotationsAttribute.visibleTag);
        }
        Annotation annot = new Annotation(LoaderConstants.CLASS_ANNOTATIONS_ORCHESTRATION, constpool);
        attr.addAnnotation(annot);
        methodDescriptor.getMethodInfo().addAttribute(attr);
    }
    cc.writeFile();
// transform the ctClass to java class
/*
         * Class<?> dynamiqueBeanClass = cc.toClass();
         * 
         * //instanciating the updated class AddOrchestration ao = (AddOrchestration) dynamiqueBeanClass.newInstance();
         * 
         * try{ Method fooMethod = ao.getClass().getDeclaredMethod(methodName, new Class<?>[] { int.class }); //getting
         * the annotation Orchestration o = (Orchestration) fooMethod.getAnnotation(Orchestration.class);
         * System.out.println("METHOD: " + fooMethod); System.out.println("ANNOTATION: " + o); } catch(Exception e){
         * e.printStackTrace(); }
         */
}
Also used : CtClass(javassist.CtClass) ConstPool(javassist.bytecode.ConstPool) ClassFile(javassist.bytecode.ClassFile) AnnotationsAttribute(javassist.bytecode.AnnotationsAttribute) ClassPool(javassist.ClassPool) CtMethod(javassist.CtMethod) Annotation(javassist.bytecode.annotation.Annotation)

Example 14 with ClassFile

use of javassist.bytecode.ClassFile in project tutorials by eugenp.

the class JavasisstUnitTest method givenJavasisstAPI_whenConstructClass_thenGenerateAClassFile.

@Test
public void givenJavasisstAPI_whenConstructClass_thenGenerateAClassFile() throws CannotCompileException, IOException, ClassNotFoundException, IllegalAccessException, InstantiationException {
    // given
    String classNameWithPackage = "com.baeldung.JavassistGeneratedClass";
    ClassFile cf = new ClassFile(false, classNameWithPackage, null);
    cf.setInterfaces(new String[] { "java.lang.Cloneable" });
    FieldInfo f = new FieldInfo(cf.getConstPool(), "id", "I");
    f.setAccessFlags(AccessFlag.PUBLIC);
    cf.addField(f);
    // when
    String className = "JavassistGeneratedClass.class";
    cf.write(new DataOutputStream(new FileOutputStream(className)));
    // then
    ClassPool classPool = ClassPool.getDefault();
    Field[] fields = classPool.makeClass(cf).toClass().getFields();
    assertEquals(fields[0].getName(), "id");
    String classContent = new String(Files.readAllBytes(Paths.get(className)));
    assertTrue(classContent.contains("java/lang/Cloneable"));
}
Also used : Field(java.lang.reflect.Field) ClassFile(javassist.bytecode.ClassFile) DataOutputStream(java.io.DataOutputStream) FileOutputStream(java.io.FileOutputStream) ClassPool(javassist.ClassPool) FieldInfo(javassist.bytecode.FieldInfo) Test(org.junit.Test)

Example 15 with ClassFile

use of javassist.bytecode.ClassFile in project tutorials by eugenp.

the class JavasisstUnitTest method givenJavaClass_whenLoadAtByJavassist_thenTraversWholeClass.

@Test
public void givenJavaClass_whenLoadAtByJavassist_thenTraversWholeClass() throws NotFoundException, CannotCompileException, BadBytecode {
    // given
    ClassPool cp = ClassPool.getDefault();
    ClassFile cf = cp.get("com.baeldung.javasisst.Point").getClassFile();
    MethodInfo minfo = cf.getMethod("move");
    CodeAttribute ca = minfo.getCodeAttribute();
    CodeIterator ci = ca.iterator();
    // when
    List<String> operations = new LinkedList<>();
    while (ci.hasNext()) {
        int index = ci.next();
        int op = ci.byteAt(index);
        operations.add(Mnemonic.OPCODE[op]);
    }
    // then
    assertEquals(operations, Arrays.asList("aload_0", "iload_1", "putfield", "aload_0", "iload_2", "putfield", "return"));
}
Also used : ClassFile(javassist.bytecode.ClassFile) CodeAttribute(javassist.bytecode.CodeAttribute) CodeIterator(javassist.bytecode.CodeIterator) ClassPool(javassist.ClassPool) MethodInfo(javassist.bytecode.MethodInfo) LinkedList(java.util.LinkedList) Test(org.junit.Test)

Aggregations

ClassFile (javassist.bytecode.ClassFile)51 DataInputStream (java.io.DataInputStream)15 ClassPool (javassist.ClassPool)15 DataOutputStream (java.io.DataOutputStream)14 CtClass (javassist.CtClass)14 AnnotationsAttribute (javassist.bytecode.AnnotationsAttribute)14 ConstPool (javassist.bytecode.ConstPool)13 ByteArrayOutputStream (java.io.ByteArrayOutputStream)12 ByteArrayInputStream (java.io.ByteArrayInputStream)11 IOException (java.io.IOException)11 MethodInfo (javassist.bytecode.MethodInfo)11 CtField (javassist.CtField)10 NotFoundException (javassist.NotFoundException)9 Annotation (javassist.bytecode.annotation.Annotation)9 Test (org.junit.Test)9 IllegalClassFormatException (java.lang.instrument.IllegalClassFormatException)8 HashSet (java.util.HashSet)7 CtMethod (javassist.CtMethod)7 FieldInfo (javassist.bytecode.FieldInfo)7 Bytecode (javassist.bytecode.Bytecode)5