Search in sources :

Example 16 with CodeAttribute

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

the class Transformer method addConstructorForInstrumentation.

private void addConstructorForInstrumentation(ClassFile file) {
    MethodInfo ret = new MethodInfo(file.getConstPool(), "<init>", Constants.ADDED_CONSTRUCTOR_DESCRIPTOR);
    Bytecode code = new Bytecode(file.getConstPool());
    // if the class does not have a constructor return
    if (!ManipulationUtils.addBogusConstructorCall(file, code)) {
        return;
    }
    CodeAttribute ca = code.toCodeAttribute();
    ca.setMaxLocals(4);
    ret.setCodeAttribute(ca);
    ret.setAccessFlags(AccessFlag.PUBLIC | AccessFlag.SYNTHETIC);
    try {
        ca.computeMaxStack();
        file.addMethod(ret);
    } catch (DuplicateMemberException e) {
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}
Also used : DuplicateMemberException(javassist.bytecode.DuplicateMemberException) CodeAttribute(javassist.bytecode.CodeAttribute) MethodInfo(javassist.bytecode.MethodInfo) BadBytecode(javassist.bytecode.BadBytecode) Bytecode(javassist.bytecode.Bytecode) IllegalClassFormatException(java.lang.instrument.IllegalClassFormatException) DuplicateMemberException(javassist.bytecode.DuplicateMemberException)

Example 17 with CodeAttribute

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

the class Transformer method addMethodForInstrumentation.

/**
 * Adds a method to a class that re can redefine when the class is reloaded
 */
private void addMethodForInstrumentation(ClassFile file) {
    try {
        MethodInfo m = new MethodInfo(file.getConstPool(), Constants.ADDED_METHOD_NAME, Constants.ADDED_METHOD_DESCRIPTOR);
        m.setAccessFlags(AccessFlag.PUBLIC | AccessFlag.SYNTHETIC);
        Bytecode b = new Bytecode(file.getConstPool(), 5, 3);
        if (BuiltinClassData.skipInstrumentation(file.getSuperclass())) {
            b.addNew(NoSuchMethodError.class.getName());
            b.add(Opcode.DUP);
            b.addInvokespecial(NoSuchMethodError.class.getName(), "<init>", "()V");
            b.add(Opcode.ATHROW);
        } else {
            // delegate to the parent class
            b.add(Bytecode.ALOAD_0);
            b.add(Bytecode.ILOAD_1);
            b.add(Bytecode.ALOAD_2);
            b.addInvokespecial(file.getSuperclass(), Constants.ADDED_METHOD_NAME, Constants.ADDED_METHOD_DESCRIPTOR);
            b.add(Bytecode.ARETURN);
        }
        CodeAttribute ca = b.toCodeAttribute();
        m.setCodeAttribute(ca);
        file.addMethod(m);
    } catch (DuplicateMemberException e) {
    // e.printStackTrace();
    }
    try {
        MethodInfo m = new MethodInfo(file.getConstPool(), Constants.ADDED_STATIC_METHOD_NAME, Constants.ADDED_METHOD_DESCRIPTOR);
        m.setAccessFlags(AccessFlag.PUBLIC | AccessFlag.STATIC | AccessFlag.SYNTHETIC);
        Bytecode b = new Bytecode(file.getConstPool(), 5, 3);
        b.addNew(NoSuchMethodError.class.getName());
        b.add(Opcode.DUP);
        b.addInvokespecial(NoSuchMethodError.class.getName(), "<init>", "()V");
        b.add(Opcode.ATHROW);
        CodeAttribute ca = b.toCodeAttribute();
        m.setCodeAttribute(ca);
        file.addMethod(m);
    } catch (DuplicateMemberException e) {
    // e.printStackTrace();
    }
}
Also used : DuplicateMemberException(javassist.bytecode.DuplicateMemberException) CodeAttribute(javassist.bytecode.CodeAttribute) MethodInfo(javassist.bytecode.MethodInfo) BadBytecode(javassist.bytecode.BadBytecode) Bytecode(javassist.bytecode.Bytecode)

Example 18 with CodeAttribute

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

the class MethodReplacementTransformer method generateBoxedConditionalCodeBlock.

/**
 * This method will take a method body and add it to an added method local
 * the bytecode is inserted inside a conditional that will only run the code
 * if the method number is correct variables are removed from the parameter
 * array and unboxed if nessesary the return value is boxed if nessesary
 * <p>
 * Much of this work is handled by helper classes
 */
private static void generateBoxedConditionalCodeBlock(int methodNumber, MethodInfo mInfo, ConstPool methodConstPool, CodeAttribute addedMethod, boolean staticMethod, boolean constructor) throws BadBytecode {
    // we need to insert a conditional
    Bytecode bc = new Bytecode(mInfo.getConstPool());
    CodeAttribute ca = (CodeAttribute) mInfo.getCodeAttribute().copy(mInfo.getConstPool(), Collections.emptyMap());
    if (staticMethod) {
        bc.addOpcode(Opcode.ILOAD_0);
    } else {
        bc.addOpcode(Opcode.ILOAD_1);
    }
    int methodCountIndex = methodConstPool.addIntegerInfo(methodNumber);
    bc.addLdc(methodCountIndex);
    bc.addOpcode(Opcode.IF_ICMPNE);
    // now we need to fix local variables and unbox parameters etc
    int addedCodeLength = mangleParameters(staticMethod, constructor, ca, mInfo.getDescriptor());
    int newMax = ca.getMaxLocals() + 2;
    if (constructor) {
        // for the extra
        newMax++;
    }
    if (newMax > addedMethod.getMaxLocals()) {
        addedMethod.setMaxLocals(newMax);
    }
    // later
    int offset = ca.getCodeLength();
    // offset is +3, 2 for the branch offset after the IF_ICMPNE and 1 to
    // take it past the end of the code
    // add the branch offset
    ManipulationUtils.add16bit(bc, offset + 3);
    // now we need to insert our generated conditional at the start of the
    // new method
    CodeIterator newInfo = ca.iterator();
    newInfo.insert(bc.get());
    // now insert the new method code at the beginning of the static method
    // code attribute
    addedMethod.iterator().insert(ca.getCode());
    // update the exception table
    int exOffset = bc.length() + addedCodeLength;
    for (int i = 0; i < mInfo.getCodeAttribute().getExceptionTable().size(); ++i) {
        int start = mInfo.getCodeAttribute().getExceptionTable().startPc(i) + exOffset;
        int end = mInfo.getCodeAttribute().getExceptionTable().endPc(i) + exOffset;
        int handler = mInfo.getCodeAttribute().getExceptionTable().handlerPc(i) + exOffset;
        int type = mInfo.getCodeAttribute().getExceptionTable().catchType(i);
        addedMethod.getExceptionTable().add(start, end, handler, type);
    }
    // rewriteFakeMethod makes sure that the return type is properly boxed
    if (!constructor) {
        rewriteFakeMethod(addedMethod.iterator(), mInfo.getDescriptor());
    }
}
Also used : CodeAttribute(javassist.bytecode.CodeAttribute) CodeIterator(javassist.bytecode.CodeIterator) BadBytecode(javassist.bytecode.BadBytecode) Bytecode(javassist.bytecode.Bytecode)

Example 19 with CodeAttribute

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

the class MethodReplacementTransformer method createRemovedMethod.

private static MethodInfo createRemovedMethod(ClassFile file, MethodData md, Class<?> oldClass, Set<MethodData> methodsToRemove) {
    if (md.getMethodName().equals("<clinit>")) {
        // if the static constructor is removed it gets added later on
        return null;
    // in the process
    }
    // load up the existing method object
    MethodInfo m = new MethodInfo(file.getConstPool(), md.getMethodName(), md.getDescriptor());
    m.setAccessFlags(md.getAccessFlags());
    // put the old annotations on the class
    if (md.getMethodName().equals("<init>")) {
        Constructor<?> meth;
        try {
            meth = md.getConstructor(oldClass);
        } catch (Exception e) {
            throw new RuntimeException("Error accessing existing constructor via reflection in not found", e);
        }
        m.addAttribute(AnnotationReplacer.duplicateAnnotationsAttribute(file.getConstPool(), meth));
    } else {
        Method meth;
        try {
            meth = md.getMethod(oldClass);
        } catch (Exception e) {
            throw new RuntimeException("Error accessing existing method via reflection in not found", e);
        }
        m.addAttribute(AnnotationReplacer.duplicateAnnotationsAttribute(file.getConstPool(), meth));
    }
    Bytecode b = new Bytecode(file.getConstPool(), 5, 3);
    b.addNew("java.lang.NoSuchMethodError");
    b.add(Opcode.DUP);
    b.addInvokespecial("java.lang.NoSuchMethodError", "<init>", "()V");
    b.add(Bytecode.ATHROW);
    CodeAttribute ca = b.toCodeAttribute();
    m.setCodeAttribute(ca);
    try {
        ca.computeMaxStack();
        file.addMethod(m);
    } catch (DuplicateMemberException e) {
        logger.error("Duplicate error", e);
    } catch (BadBytecode e) {
        logger.error("Bad bytecode", e);
    }
    methodsToRemove.add(md);
    return m;
}
Also used : DuplicateMemberException(javassist.bytecode.DuplicateMemberException) CodeAttribute(javassist.bytecode.CodeAttribute) MethodInfo(javassist.bytecode.MethodInfo) BadBytecode(javassist.bytecode.BadBytecode) Bytecode(javassist.bytecode.Bytecode) Method(java.lang.reflect.Method) DuplicateMemberException(javassist.bytecode.DuplicateMemberException) IllegalClassFormatException(java.lang.instrument.IllegalClassFormatException) IOException(java.io.IOException) BadBytecode(javassist.bytecode.BadBytecode)

Example 20 with CodeAttribute

use of javassist.bytecode.CodeAttribute in project yyl_example by Relucent.

the class GetMethodParamNameTest method getMethodParamNames.

/**
 * 获得参数名 (JDK 自带类 ,接口方法和抽象方法无法正确获取参数名)
 */
private static String[] getMethodParamNames(final Method method) throws NotFoundException {
    final String methodName = method.getName();
    final Class<?>[] methodParameterTypes = method.getParameterTypes();
    final int methodParameterCount = methodParameterTypes.length;
    final String className = method.getDeclaringClass().getName();
    final boolean isStatic = Modifier.isStatic(method.getModifiers());
    final String[] methodParametersNames = new String[methodParameterCount];
    ClassPool pool = ClassPool.getDefault();
    CtClass ctClass = pool.get(className);
    CtClass[] ctTypes = new CtClass[methodParameterTypes.length];
    for (int i = 0; i < methodParameterCount; i++) {
        ctTypes[i] = pool.get(methodParameterTypes[i].getName());
    }
    CtMethod ctMethod = ctClass.getDeclaredMethod(methodName, ctTypes);
    MethodInfo methodInfo = ctMethod.getMethodInfo();
    CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
    LocalVariableAttribute attribute = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag);
    // 如果是静态方法,第一个参数就是方法参数,非静态方法,则第一个参数是 this ,然后才是方法的参数
    if (attribute != null) {
        int variableCount = isStatic ? methodParameterCount : methodParameterCount + 1;
        for (int index = 0; index < variableCount; index++) {
            int methodParameterIndex = isStatic ? index : index - 1;
            if (0 <= methodParameterIndex && methodParameterIndex < methodParameterCount) {
                methodParametersNames[methodParameterIndex] = attribute.variableName(index);
            }
        }
    }
    return methodParametersNames;
}
Also used : ClassPool(javassist.ClassPool) CtClass(javassist.CtClass) CodeAttribute(javassist.bytecode.CodeAttribute) CtClass(javassist.CtClass) MethodInfo(javassist.bytecode.MethodInfo) LocalVariableAttribute(javassist.bytecode.LocalVariableAttribute) CtMethod(javassist.CtMethod)

Aggregations

CodeAttribute (javassist.bytecode.CodeAttribute)21 MethodInfo (javassist.bytecode.MethodInfo)17 Bytecode (javassist.bytecode.Bytecode)11 BadBytecode (javassist.bytecode.BadBytecode)10 LocalVariableAttribute (javassist.bytecode.LocalVariableAttribute)9 CodeIterator (javassist.bytecode.CodeIterator)6 CtClass (javassist.CtClass)5 DuplicateMemberException (javassist.bytecode.DuplicateMemberException)5 NotFoundException (javassist.NotFoundException)4 IOException (java.io.IOException)3 IllegalClassFormatException (java.lang.instrument.IllegalClassFormatException)3 CannotCompileException (javassist.CannotCompileException)3 ClassPool (javassist.ClassPool)3 CtMethod (javassist.CtMethod)3 ClassFile (javassist.bytecode.ClassFile)3 CompileError (javassist.compiler.CompileError)3 Javac (javassist.compiler.Javac)3 Method (java.lang.reflect.Method)2 List (java.util.List)2 ConstPool (javassist.bytecode.ConstPool)2