Search in sources :

Example 56 with BadBytecode

use of javassist.bytecode.BadBytecode 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)

Example 57 with BadBytecode

use of javassist.bytecode.BadBytecode in project javaparser by javaparser.

the class JavassistTypeDeclarationAdapter method getInterfaces.

private List<ResolvedReferenceType> getInterfaces(boolean acceptIncompleteList) {
    List<ResolvedReferenceType> interfaces = new ArrayList<>();
    try {
        if (ctClass.getGenericSignature() == null) {
            for (String interfaceType : ctClass.getClassFile().getInterfaces()) {
                try {
                    ResolvedReferenceTypeDeclaration declaration = typeSolver.solveType(JavassistUtils.internalNameToCanonicalName(interfaceType));
                    interfaces.add(new ReferenceTypeImpl(declaration, typeSolver));
                } catch (UnsolvedSymbolException e) {
                    if (!acceptIncompleteList) {
                        throw e;
                    }
                }
            }
        } else {
            SignatureAttribute.ClassSignature classSignature = SignatureAttribute.toClassSignature(ctClass.getGenericSignature());
            for (SignatureAttribute.ClassType interfaceType : classSignature.getInterfaces()) {
                try {
                    interfaces.add(JavassistUtils.signatureTypeToType(interfaceType, typeSolver, typeDeclaration).asReferenceType());
                } catch (UnsolvedSymbolException e) {
                    if (!acceptIncompleteList) {
                        throw e;
                    }
                }
            }
        }
    } catch (BadBytecode e) {
        throw new RuntimeException(e);
    }
    return interfaces;
}
Also used : UnsolvedSymbolException(com.github.javaparser.resolution.UnsolvedSymbolException) SignatureAttribute(javassist.bytecode.SignatureAttribute) ResolvedReferenceTypeDeclaration(com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration) ResolvedReferenceType(com.github.javaparser.resolution.types.ResolvedReferenceType) ReferenceTypeImpl(com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl) ArrayList(java.util.ArrayList) BadBytecode(javassist.bytecode.BadBytecode)

Example 58 with BadBytecode

use of javassist.bytecode.BadBytecode in project droolsjbpm-integration by kiegroup.

the class BytecodeInjectReactive method enhanceAttributesAccess.

protected void enhanceAttributesAccess(Map<String, CtField> fieldsMap, CtClass managedCtClass) throws Exception {
    final ConstPool constPool = managedCtClass.getClassFile().getConstPool();
    final ClassPool classPool = managedCtClass.getClassPool();
    for (Object oMethod : managedCtClass.getClassFile().getMethods()) {
        final MethodInfo methodInfo = (MethodInfo) oMethod;
        final String methodName = methodInfo.getName();
        // skip methods added by enhancement, and abstract methods (methods without any code)
        if (methodName.startsWith(DROOLS_PREFIX) || methodInfo.getCodeAttribute() == null) {
            continue;
        }
        try {
            final CodeIterator itr = methodInfo.getCodeAttribute().iterator();
            while (itr.hasNext()) {
                final int index = itr.next();
                final int op = itr.byteAt(index);
                if (op != Opcode.PUTFIELD && op != Opcode.GETFIELD) {
                    continue;
                }
                final String fieldName = constPool.getFieldrefName(itr.u16bitAt(index + 1));
                CtField ctField = fieldsMap.get(fieldName);
                if (ctField == null) {
                    continue;
                }
                // if we are in constructors, only need to intercept assignment statement for Reactive Collection/List/... (regardless they may be final)
                if (methodInfo.isConstructor() && !(isCtFieldACollection(ctField))) {
                    continue;
                }
                if (op == Opcode.PUTFIELD) {
                    // addMethod is a safe add, if constant already present it return the existing value without adding.
                    final int methodIndex = addMethod(constPool, writeMethods.get(fieldName));
                    itr.writeByte(Opcode.INVOKEVIRTUAL, index);
                    itr.write16bit(methodIndex, index + 1);
                }
            }
            methodInfo.getCodeAttribute().setAttribute(MapMaker.make(classPool, methodInfo));
        } catch (BadBytecode bb) {
            final String msg = String.format("Unable to perform field access transformation in method [%s]", methodName);
            throw new Exception(msg, bb);
        }
    }
}
Also used : ConstPool(javassist.bytecode.ConstPool) CodeIterator(javassist.bytecode.CodeIterator) CtField(javassist.CtField) ClassPool(javassist.ClassPool) ReactiveObject(org.drools.core.phreak.ReactiveObject) MethodInfo(javassist.bytecode.MethodInfo) BadBytecode(javassist.bytecode.BadBytecode) NotFoundException(javassist.NotFoundException) CannotCompileException(javassist.CannotCompileException)

Example 59 with BadBytecode

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

the class JavassistMethod method insertCatch.

private void insertCatch(int from, String src, CtClass exceptionType, String exceptionName) throws CannotCompileException {
    CtClass cc = behavior.getDeclaringClass();
    ConstPool cp = behavior.getMethodInfo().getConstPool();
    CodeAttribute ca = behavior.getMethodInfo().getCodeAttribute();
    CodeIterator iterator = ca.iterator();
    Bytecode b = new Bytecode(cp, ca.getMaxStack(), ca.getMaxLocals());
    b.setStackDepth(1);
    Javac jv = new Javac(b, cc);
    try {
        jv.recordParams(behavior.getParameterTypes(), Modifier.isStatic(getModifiers()));
        jv.recordLocalVariables(ca, from);
        int var = jv.recordVariable(exceptionType, exceptionName);
        b.addAstore(var);
        jv.compileStmnt(src);
        int stack = b.getMaxStack();
        int locals = b.getMaxLocals();
        if (stack > ca.getMaxStack())
            ca.setMaxStack(stack);
        if (locals > ca.getMaxLocals())
            ca.setMaxLocals(locals);
        int len = iterator.getCodeLength();
        int pos = iterator.append(b.get());
        ca.getExceptionTable().add(from, len, len, cp.addClassInfo(exceptionType));
        iterator.append(b.getExceptionTable(), pos);
        behavior.getMethodInfo().rebuildStackMapIf6(cc.getClassPool(), cc.getClassFile2());
    } catch (NotFoundException e) {
        throw new CannotCompileException(e);
    } catch (CompileError e) {
        throw new CannotCompileException(e);
    } catch (BadBytecode e) {
        throw new CannotCompileException(e);
    }
}
Also used : CompileError(javassist.compiler.CompileError) CtClass(javassist.CtClass) ConstPool(javassist.bytecode.ConstPool) Javac(javassist.compiler.Javac) CodeAttribute(javassist.bytecode.CodeAttribute) CodeIterator(javassist.bytecode.CodeIterator) NotFoundException(javassist.NotFoundException) BadBytecode(javassist.bytecode.BadBytecode) Bytecode(javassist.bytecode.Bytecode) CannotCompileException(javassist.CannotCompileException) BadBytecode(javassist.bytecode.BadBytecode)

Example 60 with BadBytecode

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

the class JavassistMethod method insertBeforeConstructor.

private int insertBeforeConstructor(int pos, String src) throws CannotCompileException {
    CtClass cc = behavior.getDeclaringClass();
    CodeAttribute ca = behavior.getMethodInfo().getCodeAttribute();
    CodeIterator iterator = ca.iterator();
    Bytecode b = new Bytecode(behavior.getMethodInfo().getConstPool(), ca.getMaxStack(), ca.getMaxLocals());
    b.setStackDepth(ca.getMaxStack());
    Javac jv = new Javac(b, cc);
    try {
        jv.recordParams(behavior.getParameterTypes(), false);
        jv.recordLocalVariables(ca, 0);
        jv.compileStmnt(src);
        ca.setMaxStack(b.getMaxStack());
        ca.setMaxLocals(b.getMaxLocals());
        iterator.skipConstructor();
        if (pos != -1) {
            iterator.insertEx(pos, b.get());
        } else {
            pos = iterator.insertEx(b.get());
        }
        iterator.insert(b.getExceptionTable(), pos);
        behavior.getMethodInfo().rebuildStackMapIf6(cc.getClassPool(), cc.getClassFile2());
        return pos + b.length();
    } catch (NotFoundException e) {
        throw new CannotCompileException(e);
    } catch (CompileError e) {
        throw new CannotCompileException(e);
    } catch (BadBytecode e) {
        throw new CannotCompileException(e);
    }
}
Also used : CompileError(javassist.compiler.CompileError) CtClass(javassist.CtClass) Javac(javassist.compiler.Javac) CodeAttribute(javassist.bytecode.CodeAttribute) CodeIterator(javassist.bytecode.CodeIterator) NotFoundException(javassist.NotFoundException) BadBytecode(javassist.bytecode.BadBytecode) Bytecode(javassist.bytecode.Bytecode) CannotCompileException(javassist.CannotCompileException) BadBytecode(javassist.bytecode.BadBytecode)

Aggregations

BadBytecode (javassist.bytecode.BadBytecode)135 Bytecode (javassist.bytecode.Bytecode)57 CodeAttribute (javassist.bytecode.CodeAttribute)56 CodeIterator (javassist.bytecode.CodeIterator)43 MethodInfo (javassist.bytecode.MethodInfo)38 CtClass (javassist.CtClass)32 NotFoundException (javassist.NotFoundException)32 ConstPool (javassist.bytecode.ConstPool)30 Javac (javassist.compiler.Javac)27 CompileError (javassist.compiler.CompileError)26 CannotCompileException (javassist.CannotCompileException)22 ClassPool (javassist.ClassPool)12 List (java.util.List)11 Type (javassist.bytecode.analysis.Type)8 DuplicateMemberException (javassist.bytecode.DuplicateMemberException)7 IOException (java.io.IOException)6 CtMethod (javassist.CtMethod)5 ClassFile (javassist.bytecode.ClassFile)5 IllegalClassFormatException (java.lang.instrument.IllegalClassFormatException)4 Method (java.lang.reflect.Method)4