Search in sources :

Example 1 with CodeAttribute

use of javassist.bytecode.CodeAttribute in project pinpoint by naver.

the class JavaAssistUtils method lookupLocalVariableAttribute.

/**
     * get LocalVariableAttribute
     *
     * @param method
     * @return null if the class is not compiled with debug option
     */
public static LocalVariableAttribute lookupLocalVariableAttribute(CtBehavior method) {
    if (method == null) {
        throw new NullPointerException("method must not be null");
    }
    MethodInfo methodInfo = method.getMethodInfo2();
    CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
    if (codeAttribute == null) {
        return null;
    }
    AttributeInfo localVariableTable = codeAttribute.getAttribute(LocalVariableAttribute.tag);
    LocalVariableAttribute local = (LocalVariableAttribute) localVariableTable;
    return local;
}
Also used : AttributeInfo(javassist.bytecode.AttributeInfo) CodeAttribute(javassist.bytecode.CodeAttribute) MethodInfo(javassist.bytecode.MethodInfo) LocalVariableAttribute(javassist.bytecode.LocalVariableAttribute)

Example 2 with CodeAttribute

use of javassist.bytecode.CodeAttribute in project hibernate-orm by hibernate.

the class BulkAccessorFactory method addSetter.

private void addSetter(ClassFile classfile, final Method[] setters) throws CannotCompileException {
    final ConstPool constPool = classfile.getConstPool();
    final int targetTypeConstPoolIndex = constPool.addClassInfo(this.targetBean.getName());
    final String desc = GET_SETTER_DESC;
    final MethodInfo setterMethodInfo = new MethodInfo(constPool, GENERATED_SETTER_NAME, desc);
    final Bytecode code = new Bytecode(constPool, 4, 6);
    StackMapTable stackmap = null;
    /* | this | bean | args | i | raw bean | exception | */
    if (setters.length > 0) {
        // required to exception table
        int start;
        int end;
        // iconst_0 // i
        code.addIconst(0);
        // istore_3 // store i
        code.addIstore(3);
        // aload_1 // load the bean
        code.addAload(1);
        // checkcast // cast the bean into a raw bean
        code.addCheckcast(this.targetBean.getName());
        // astore 4 // store the raw bean
        code.addAstore(4);
        /* current stack len = 0 */
        // start region to handling exception (BulkAccessorException)
        start = code.currentPc();
        int lastIndex = 0;
        for (int i = 0; i < setters.length; ++i) {
            if (setters[i] != null) {
                final int diff = i - lastIndex;
                if (diff > 0) {
                    // iinc 3, 1
                    code.addOpcode(Opcode.IINC);
                    code.add(3);
                    code.add(diff);
                    lastIndex = i;
                }
            }
            /* current stack len = 0 */
            // aload 4 // load the raw bean
            code.addAload(4);
            // aload_2 // load the args
            code.addAload(2);
            // iconst_i
            code.addIconst(i);
            // aaload
            code.addOpcode(Opcode.AALOAD);
            // checkcast
            final Class[] setterParamTypes = setters[i].getParameterTypes();
            final Class setterParamType = setterParamTypes[0];
            if (setterParamType.isPrimitive()) {
                // checkcast (case of primitive type)
                // invokevirtual (case of primitive type)
                this.addUnwrapper(code, setterParamType);
            } else {
                // checkcast (case of reference type)
                code.addCheckcast(setterParamType.getName());
            }
            /* current stack len = 2 */
            final String rawSetterMethodDesc = RuntimeSupport.makeDescriptor(setters[i]);
            if (!this.targetBean.isInterface()) {
                // invokevirtual
                code.addInvokevirtual(targetTypeConstPoolIndex, setters[i].getName(), rawSetterMethodDesc);
            } else {
                // invokeinterface
                final Class[] params = setters[i].getParameterTypes();
                int size;
                if (params[0].equals(Double.TYPE) || params[0].equals(Long.TYPE)) {
                    size = 3;
                } else {
                    size = 2;
                }
                code.addInvokeinterface(targetTypeConstPoolIndex, setters[i].getName(), rawSetterMethodDesc, size);
            }
        }
        // end region to handling exception (BulkAccessorException)
        end = code.currentPc();
        // return
        code.addOpcode(Opcode.RETURN);
        /* current stack len = 0 */
        // register in exception table
        final int throwableTypeIndex = constPool.addClassInfo(THROWABLE_CLASS_NAME);
        final int handlerPc = code.currentPc();
        code.addExceptionHandler(start, end, handlerPc, throwableTypeIndex);
        // astore 5 // store exception
        code.addAstore(5);
        // new // BulkAccessorException
        code.addNew(BULKEXCEPTION_CLASS_NAME);
        // dup
        code.addOpcode(Opcode.DUP);
        // aload 5 // load exception
        code.addAload(5);
        // iload_3 // i
        code.addIload(3);
        // invokespecial // BulkAccessorException.<init>
        final String consDesc = "(Ljava/lang/Throwable;I)V";
        code.addInvokespecial(BULKEXCEPTION_CLASS_NAME, MethodInfo.nameInit, consDesc);
        // athrow
        code.addOpcode(Opcode.ATHROW);
        final StackMapTable.Writer writer = new StackMapTable.Writer(32);
        final int[] localTags = { StackMapTable.OBJECT, StackMapTable.OBJECT, StackMapTable.OBJECT, StackMapTable.INTEGER };
        final int[] localData = { constPool.getThisClassInfo(), constPool.addClassInfo("java/lang/Object"), constPool.addClassInfo("[Ljava/lang/Object;"), 0 };
        final int[] stackTags = { StackMapTable.OBJECT };
        final int[] stackData = { throwableTypeIndex };
        writer.fullFrame(handlerPc, localTags, localData, stackTags, stackData);
        stackmap = writer.toStackMapTable(constPool);
    } else {
        // return
        code.addOpcode(Opcode.RETURN);
    }
    final CodeAttribute ca = code.toCodeAttribute();
    if (stackmap != null) {
        ca.setAttribute(stackmap);
    }
    setterMethodInfo.setCodeAttribute(ca);
    setterMethodInfo.setAccessFlags(AccessFlag.PUBLIC);
    classfile.addMethod(setterMethodInfo);
}
Also used : ConstPool(javassist.bytecode.ConstPool) CodeAttribute(javassist.bytecode.CodeAttribute) MethodInfo(javassist.bytecode.MethodInfo) Bytecode(javassist.bytecode.Bytecode) StackMapTable(javassist.bytecode.StackMapTable)

Example 3 with CodeAttribute

use of javassist.bytecode.CodeAttribute in project latke by b3log.

the class Reflections method getMethodVariableNames.

/**
 * getMethodVariableNames in user defined.
 *
 * @param clazz            the specific clazz
 * @param targetMethodName the targetMethodName
 * @param types            the types of the method parameters
 * @return the String[] of names
 */
public static String[] getMethodVariableNames(final Class<?> clazz, final String targetMethodName, final Class<?>[] types) {
    CtClass cc;
    CtMethod cm = null;
    try {
        if (null == CLASS_POOL.find(clazz.getName())) {
            CLASS_POOL.insertClassPath(new ClassClassPath(clazz));
        }
        cc = CLASS_POOL.get(clazz.getName());
        final CtClass[] ptypes = new CtClass[types.length];
        for (int i = 0; i < ptypes.length; i++) {
            ptypes[i] = CLASS_POOL.get(types[i].getName());
        }
        cm = cc.getDeclaredMethod(targetMethodName, ptypes);
    } catch (final NotFoundException e) {
        LOGGER.log(Level.ERROR, "Get method variable names failed", e);
    }
    if (null == cm) {
        return new String[types.length];
    }
    final MethodInfo methodInfo = cm.getMethodInfo();
    final CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
    final LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag);
    String[] variableNames = new String[0];
    try {
        variableNames = new String[cm.getParameterTypes().length];
    } catch (final NotFoundException e) {
        LOGGER.log(Level.ERROR, "Get method variable names failed", e);
    }
    // final int staticIndex = Modifier.isStatic(cm.getModifiers()) ? 0 : 1;
    int j = -1;
    String variableName = null;
    Boolean ifkill = false;
    while (!"this".equals(variableName)) {
        j++;
        variableName = attr.variableName(j);
        // to prevent heap error when there being some unknown reasons to resolve the VariableNames
        if (j > MAX_FIND_LENGTH) {
            LOGGER.log(Level.WARN, "Maybe resolve to VariableNames error [class=" + clazz.getName() + ", targetMethodName=" + targetMethodName + ']');
            ifkill = true;
            break;
        }
    }
    if (!ifkill) {
        for (int i = 0; i < variableNames.length; i++) {
            variableNames[i] = attr.variableName(++j);
        }
    }
    return variableNames;
}
Also used : CodeAttribute(javassist.bytecode.CodeAttribute) MethodInfo(javassist.bytecode.MethodInfo) LocalVariableAttribute(javassist.bytecode.LocalVariableAttribute)

Example 4 with CodeAttribute

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

the class WildflyClassTransformer method transform.

@Override
public boolean transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, ClassFile file, Set<Class<?>> classesToRetransform, ChangedClassImpl changedClass, Set<MethodInfo> modifiedMethods) throws IllegalClassFormatException, BadBytecode, DuplicateMemberException {
    if (!file.getName().equals("org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService")) {
        return false;
    }
    for (MethodInfo method : (List<MethodInfo>) file.getMethods()) {
        if (method.getName().equals("createServletConfig")) {
            CodeAttribute code = method.getCodeAttribute();
            code.setMaxStack(code.getMaxStack() + 1);
            CodeIterator it = code.iterator();
            modifiedMethods.add(method);
            while (it.hasNext()) {
                int pos = it.next();
                int inst = it.byteAt(pos);
                if (inst == CodeAttribute.ARETURN) {
                    Bytecode b = new Bytecode(method.getConstPool());
                    b.addGetstatic("org.fakereplace.integration.wildfly.autoupdate.WebUpdateHandlerWrapper", "INSTANCE", "Lio/undertow/server/HandlerWrapper;");
                    b.addInvokevirtual("io.undertow.servlet.api.DeploymentInfo", "addInnerHandlerChainWrapper", "(Lio/undertow/server/HandlerWrapper;)Lio/undertow/servlet/api/DeploymentInfo;");
                    it.insert(pos, b.get());
                }
            }
        }
    }
    return true;
}
Also used : CodeAttribute(javassist.bytecode.CodeAttribute) CodeIterator(javassist.bytecode.CodeIterator) MethodInfo(javassist.bytecode.MethodInfo) List(java.util.List) BadBytecode(javassist.bytecode.BadBytecode) Bytecode(javassist.bytecode.Bytecode)

Example 5 with CodeAttribute

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

the class MethodReplacementTransformer method transform.

@Override
public boolean transform(ClassLoader loader, String className, Class<?> oldClass, ProtectionDomain protectionDomain, ClassFile file, Set<Class<?>> classesToRetransform, ChangedClassImpl changedClass, Set<MethodInfo> modifiedMethods) throws IllegalClassFormatException, BadBytecode, DuplicateMemberException {
    if (oldClass == null || className == null) {
        return false;
    }
    final Set<MethodData> methodsToRemove = new HashSet<>();
    final Set<FakeMethod> methodsToAdd = new HashSet<>();
    final Set<FakeMethod> constructorsToAdd = new HashSet<>();
    BaseClassData data = ClassDataStore.instance().getBaseClassData(loader, className);
    // state for added static methods
    CodeAttribute staticCodeAttribute = null, virtualCodeAttribute = null, constructorCodeAttribute = null;
    try {
        // stick our added methods into the class file
        // we can't finalise the code yet because we will probably need
        // the add stuff to them
        MethodInfo virtMethod = new MethodInfo(file.getConstPool(), Constants.ADDED_METHOD_NAME, Constants.ADDED_METHOD_DESCRIPTOR);
        modifiedMethods.add(virtMethod);
        virtMethod.setAccessFlags(AccessFlag.PUBLIC);
        if (file.isInterface()) {
            virtMethod.setAccessFlags(AccessFlag.PUBLIC | AccessFlag.ABSTRACT | AccessFlag.SYNTHETIC);
        } else {
            virtMethod.setAccessFlags(AccessFlag.PUBLIC | AccessFlag.SYNTHETIC);
            Bytecode b = new Bytecode(file.getConstPool(), 0, 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 {
                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);
            }
            virtualCodeAttribute = b.toCodeAttribute();
            virtMethod.setCodeAttribute(virtualCodeAttribute);
            MethodInfo m = new MethodInfo(file.getConstPool(), Constants.ADDED_STATIC_METHOD_NAME, Constants.ADDED_METHOD_DESCRIPTOR);
            modifiedMethods.add(m);
            m.setAccessFlags(AccessFlag.PUBLIC | AccessFlag.STATIC | AccessFlag.SYNTHETIC);
            b = new Bytecode(file.getConstPool(), 0, 3);
            b.addNew(NoSuchMethodError.class.getName());
            b.add(Opcode.DUP);
            b.addInvokespecial(NoSuchMethodError.class.getName(), "<init>", "()V");
            b.add(Opcode.ATHROW);
            staticCodeAttribute = b.toCodeAttribute();
            m.setCodeAttribute(staticCodeAttribute);
            file.addMethod(m);
            m = new MethodInfo(file.getConstPool(), "<init>", Constants.ADDED_CONSTRUCTOR_DESCRIPTOR);
            modifiedMethods.add(m);
            m.setAccessFlags(AccessFlag.PUBLIC | AccessFlag.SYNTHETIC);
            b = new Bytecode(file.getConstPool(), 0, 4);
            if (ManipulationUtils.addBogusConstructorCall(file, b)) {
                constructorCodeAttribute = b.toCodeAttribute();
                m.setCodeAttribute(constructorCodeAttribute);
                constructorCodeAttribute.setMaxLocals(6);
                file.addMethod(m);
            }
        }
        file.addMethod(virtMethod);
    } catch (DuplicateMemberException e) {
        e.printStackTrace();
    }
    Set<MethodData> methods = new HashSet<>();
    methods.addAll(data.getMethods());
    ListIterator<?> it = file.getMethods().listIterator();
    // IncompatibleClassChange exception will be thrown
    while (it.hasNext()) {
        MethodInfo m = (MethodInfo) it.next();
        MethodData md = null;
        boolean upgradedVisibility = false;
        for (MethodData i : methods) {
            if (i.getMethodName().equals(m.getName()) && i.getDescriptor().equals(m.getDescriptor())) {
                // depends on what has changed
                if (i.getAccessFlags() != m.getAccessFlags()) {
                    if (AccessFlagUtils.upgradeVisibility(m.getAccessFlags(), i.getAccessFlags())) {
                        upgradedVisibility = true;
                    } else if (AccessFlagUtils.downgradeVisibility(m.getAccessFlags(), i.getAccessFlags())) {
                    // ignore this, we don't need to do anything
                    } else {
                        // we can't handle this yet
                        continue;
                    }
                }
                m.setAccessFlags(i.getAccessFlags());
                // if it is the constructor
                if (m.getName().equals("<init>")) {
                    try {
                        Constructor<?> meth = i.getConstructor(oldClass);
                        AnnotationDataStore.recordConstructorAnnotations(meth, (AnnotationsAttribute) m.getAttribute(AnnotationsAttribute.visibleTag));
                        AnnotationDataStore.recordConstructorParameterAnnotations(meth, (ParameterAnnotationsAttribute) m.getAttribute(ParameterAnnotationsAttribute.visibleTag));
                        // now revert the annotations:
                        m.addAttribute(AnnotationReplacer.duplicateAnnotationsAttribute(file.getConstPool(), meth));
                        m.addAttribute(AnnotationReplacer.duplicateParameterAnnotationsAttribute(file.getConstPool(), meth));
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                } else if (!m.getName().equals("<clinit>")) {
                    // we do not have to worry about them
                    try {
                        Method meth = i.getMethod(oldClass);
                        AnnotationDataStore.recordMethodAnnotations(meth, (AnnotationsAttribute) m.getAttribute(AnnotationsAttribute.visibleTag));
                        AnnotationDataStore.recordMethodParameterAnnotations(meth, (ParameterAnnotationsAttribute) m.getAttribute(ParameterAnnotationsAttribute.visibleTag));
                        // now revert the annotations:
                        m.addAttribute(AnnotationReplacer.duplicateAnnotationsAttribute(file.getConstPool(), meth));
                        m.addAttribute(AnnotationReplacer.duplicateParameterAnnotationsAttribute(file.getConstPool(), meth));
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                }
                md = i;
                break;
            }
        }
        // we do not need to deal with these
        if (m.getName().equals(Constants.ADDED_METHOD_NAME) || m.getName().equals(Constants.ADDED_STATIC_METHOD_NAME)) {
            break;
        }
        // so it is still in the original
        if (md == null || upgradedVisibility) {
            if ((m.getAccessFlags() & AccessFlag.STATIC) != 0) {
                Class<?> c = addMethod(file, loader, m, methodsToAdd, staticCodeAttribute, true, oldClass);
                if (c != null) {
                    classesToRetransform.add(c);
                }
            } else if ((m.getName().equals("<init>"))) {
                addConstructor(file, loader, m, constructorsToAdd, constructorCodeAttribute, oldClass);
            } else if (m.getName().equals("<clinit>")) {
            // nop, we can't change this, just ignore it
            } else {
                Class<?> c = addMethod(file, loader, m, methodsToAdd, virtualCodeAttribute, false, oldClass);
                if (c != null) {
                    classesToRetransform.add(c);
                }
            }
            if (!upgradedVisibility) {
                it.remove();
            }
        } else {
            methods.remove(md);
        }
        if (upgradedVisibility) {
            methods.remove(md);
        }
    }
    for (MethodData md : methods) {
        if (md.getType() == MemberType.NORMAL) {
            MethodInfo removedMethod = createRemovedMethod(file, md, oldClass, methodsToRemove);
            if (removedMethod != null) {
                modifiedMethods.add(removedMethod);
            }
        }
    }
    ClassDataStore.instance().modifyCurrentData(loader, className, (builder) -> {
        for (MethodData method : methodsToRemove) {
            builder.removeMethod(method);
        }
        for (FakeMethod fake : methodsToAdd) {
            ClassDataStore.instance().registerReplacedMethod(fake.proxyName, builder.addFakeMethod(fake.name, fake.descriptor, fake.proxyName, fake.accessFlags));
        }
        for (FakeMethod fake : constructorsToAdd) {
            ClassDataStore.instance().registerReplacedMethod(fake.proxyName, builder.addFakeConstructor(fake.name, fake.descriptor, fake.proxyName, fake.accessFlags, fake.methodCount));
        }
    });
    // the method declaration to propagate the call to the parent
    if (!file.isInterface()) {
        try {
            staticCodeAttribute.computeMaxStack();
            virtualCodeAttribute.computeMaxStack();
            if (constructorCodeAttribute != null) {
                constructorCodeAttribute.computeMaxStack();
            }
        } catch (BadBytecode e) {
            e.printStackTrace();
        }
    }
    return true;
}
Also used : DuplicateMemberException(javassist.bytecode.DuplicateMemberException) ParameterAnnotationsAttribute(javassist.bytecode.ParameterAnnotationsAttribute) ParameterAnnotationsAttribute(javassist.bytecode.ParameterAnnotationsAttribute) AnnotationsAttribute(javassist.bytecode.AnnotationsAttribute) Method(java.lang.reflect.Method) DuplicateMemberException(javassist.bytecode.DuplicateMemberException) IllegalClassFormatException(java.lang.instrument.IllegalClassFormatException) IOException(java.io.IOException) BadBytecode(javassist.bytecode.BadBytecode) BaseClassData(org.fakereplace.data.BaseClassData) CodeAttribute(javassist.bytecode.CodeAttribute) MethodData(org.fakereplace.data.MethodData) MethodInfo(javassist.bytecode.MethodInfo) BadBytecode(javassist.bytecode.BadBytecode) Bytecode(javassist.bytecode.Bytecode) HashSet(java.util.HashSet)

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