Search in sources :

Example 1 with Bytecode

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

the class BulkAccessorFactory method addGetter.

private void addGetter(ClassFile classfile, final Method[] getters) throws CannotCompileException {
    final ConstPool constPool = classfile.getConstPool();
    final int targetBeanConstPoolIndex = constPool.addClassInfo(this.targetBean.getName());
    final String desc = GET_SETTER_DESC;
    final MethodInfo getterMethodInfo = new MethodInfo(constPool, GENERATED_GETTER_NAME, desc);
    final Bytecode code = new Bytecode(constPool, 6, 4);
    /* | this | bean | args | raw bean | */
    if (getters.length >= 0) {
        // aload_1 // load bean
        code.addAload(1);
        // checkcast // cast bean
        code.addCheckcast(this.targetBean.getName());
        // astore_3 // store bean
        code.addAstore(3);
        for (int i = 0; i < getters.length; ++i) {
            if (getters[i] != null) {
                final Method getter = getters[i];
                // aload_2 // args
                code.addAload(2);
                // iconst_i // continue to aastore
                // growing stack is 1
                code.addIconst(i);
                final Class returnType = getter.getReturnType();
                int typeIndex = -1;
                if (returnType.isPrimitive()) {
                    typeIndex = FactoryHelper.typeIndex(returnType);
                    // new
                    code.addNew(FactoryHelper.wrapperTypes[typeIndex]);
                    // dup
                    code.addOpcode(Opcode.DUP);
                }
                // aload_3 // load the raw bean
                code.addAload(3);
                final String getterSignature = RuntimeSupport.makeDescriptor(getter);
                final String getterName = getter.getName();
                if (this.targetBean.isInterface()) {
                    // invokeinterface
                    code.addInvokeinterface(targetBeanConstPoolIndex, getterName, getterSignature, 1);
                } else {
                    // invokevirtual
                    code.addInvokevirtual(targetBeanConstPoolIndex, getterName, getterSignature);
                }
                if (typeIndex >= 0) {
                    // is a primitive type
                    // invokespecial
                    code.addInvokespecial(FactoryHelper.wrapperTypes[typeIndex], MethodInfo.nameInit, FactoryHelper.wrapperDesc[typeIndex]);
                }
                // aastore // args
                code.add(Opcode.AASTORE);
                code.growStack(-3);
            }
        }
    }
    // return
    code.addOpcode(Opcode.RETURN);
    getterMethodInfo.setCodeAttribute(code.toCodeAttribute());
    getterMethodInfo.setAccessFlags(AccessFlag.PUBLIC);
    classfile.addMethod(getterMethodInfo);
}
Also used : ConstPool(javassist.bytecode.ConstPool) MethodInfo(javassist.bytecode.MethodInfo) Bytecode(javassist.bytecode.Bytecode) Method(java.lang.reflect.Method)

Example 2 with Bytecode

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

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

the class WeldClassTransformer 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 {
    // Hack up the proxy factory so it stores the proxy ClassFile. We need this to regenerate proxies.
    if (file.getName().equals(ORG_JBOSS_WELD_BEAN_PROXY_PROXY_FACTORY)) {
        for (final MethodInfo method : (List<MethodInfo>) file.getMethods()) {
            if (method.getName().equals("createProxyClass")) {
                modifiedMethods.add(method);
                final VirtualToStaticManipulator virtualToStaticManipulator = new VirtualToStaticManipulator();
                virtualToStaticManipulator.replaceVirtualMethodInvokationWithStatic(ClassLoader.class.getName(), WELD_PROXY_CLASS_LOADING_DELEGATE, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;", "(Ljava/lang/ClassLoader;Ljava/lang/String;)Ljava/lang/Class;", loader);
                virtualToStaticManipulator.replaceVirtualMethodInvokationWithStatic("org.jboss.weld.util.bytecode.ClassFileUtils", WELD_PROXY_CLASS_LOADING_DELEGATE, "toClass", "(Lorg/jboss/classfilewriter/ClassFile;Ljava/lang/ClassLoader;Ljava/security/ProtectionDomain;)Ljava/lang/Class;", "(Lorg/jboss/classfilewriter/ClassFile;Ljava/lang/ClassLoader;Ljava/security/ProtectionDomain;)Ljava/lang/Class;", loader);
                virtualToStaticManipulator.transformClass(file, loader, true, modifiedMethods);
                return true;
            } else if (method.getName().equals("<init>")) {
                modifiedMethods.add(method);
                Integer beanArgument = null;
                int count = 1;
                for (final String paramType : DescriptorUtils.descriptorStringToParameterArray(method.getDescriptor())) {
                    if (paramType.equals("Ljavax/enterprise/inject/spi/Bean")) {
                        beanArgument = count;
                        break;
                    } else if (paramType.equals("D") || paramType.equals("J")) {
                        count += 2;
                    } else {
                        count++;
                    }
                }
                if (beanArgument == null) {
                    log.error("Constructor org.jboss.weld.bean.proxy.ProxyFactory.<init>" + method.getDescriptor() + " does not have a bean parameter, proxies produced by this factory will not be reloadable");
                    continue;
                }
                // similar to other tracked instances
                // but we need a strong ref
                Bytecode code = new Bytecode(file.getConstPool());
                code.addAload(0);
                code.addAload(beanArgument);
                code.addInvokestatic(WeldClassChangeAware.class.getName(), "addProxyFactory", "(Ljava/lang/Object;Ljava/lang/Object;)V");
                CodeIterator it = method.getCodeAttribute().iterator();
                it.skipConstructor();
                it.insert(code.get());
            }
        }
    }
    return false;
}
Also used : VirtualToStaticManipulator(org.fakereplace.manip.VirtualToStaticManipulator) CodeIterator(javassist.bytecode.CodeIterator) MethodInfo(javassist.bytecode.MethodInfo) List(java.util.List) BadBytecode(javassist.bytecode.BadBytecode) Bytecode(javassist.bytecode.Bytecode)

Example 4 with Bytecode

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

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

the class MethodReplacementTransformer method generateFakeConstructorBytecode.

/**
 * creates a class with a fake constructor that can be used by the reflection
 * api
 * <p>
 * Constructors are not invoked through the proxy class, instead we have to
 * do a lot more bytecode re-writing at the actual invocation sites
 */
private static String generateFakeConstructorBytecode(MethodInfo mInfo, ClassLoader loader) throws BadBytecode {
    String proxyName = ProxyDefinitionStore.getProxyName();
    ClassFile proxy = new ClassFile(false, proxyName, "java.lang.Object");
    proxy.setVersionToJava5();
    proxy.setAccessFlags(AccessFlag.PUBLIC);
    // add our new annotations directly onto the new proxy method. This way
    // they will just work without registering them with the
    // AnnotationDataStore
    String[] types = DescriptorUtils.descriptorStringToParameterArray(mInfo.getDescriptor());
    // as this method is never called the bytecode just returns
    Bytecode b = new Bytecode(proxy.getConstPool());
    b.add(Opcode.ALOAD_0);
    b.addInvokespecial("java.lang.Object", "<init>", "()V");
    b.add(Opcode.RETURN);
    MethodInfo method = new MethodInfo(proxy.getConstPool(), mInfo.getName(), mInfo.getDescriptor());
    method.setAccessFlags(mInfo.getAccessFlags());
    method.setCodeAttribute(b.toCodeAttribute());
    method.getCodeAttribute().computeMaxStack();
    method.getCodeAttribute().setMaxLocals(types.length + 1);
    copyMethodAttributes(mInfo, method);
    try {
        proxy.addMethod(method);
    } 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) BadBytecode(javassist.bytecode.BadBytecode) Bytecode(javassist.bytecode.Bytecode) MethodInfo(javassist.bytecode.MethodInfo) ByteArrayOutputStream(java.io.ByteArrayOutputStream) IOException(java.io.IOException)

Aggregations

Bytecode (javassist.bytecode.Bytecode)36 MethodInfo (javassist.bytecode.MethodInfo)28 BadBytecode (javassist.bytecode.BadBytecode)24 CodeIterator (javassist.bytecode.CodeIterator)15 CodeAttribute (javassist.bytecode.CodeAttribute)11 ConstPool (javassist.bytecode.ConstPool)11 DuplicateMemberException (javassist.bytecode.DuplicateMemberException)8 IOException (java.io.IOException)6 List (java.util.List)6 ClassFile (javassist.bytecode.ClassFile)5 ByteArrayOutputStream (java.io.ByteArrayOutputStream)4 DataOutputStream (java.io.DataOutputStream)4 IllegalClassFormatException (java.lang.instrument.IllegalClassFormatException)4 Method (java.lang.reflect.Method)4 HashSet (java.util.HashSet)4 NotFoundException (javassist.NotFoundException)4 JumpMarker (org.fakereplace.util.JumpMarker)4 HashMap (java.util.HashMap)3 Set (java.util.Set)3 CannotCompileException (javassist.CannotCompileException)3