Package javassist.bytecode

Examples of javassist.bytecode.CodeAttribute


    private static final Logger logger = Logger.getLogger(MethodReplacer.class);

    public static void handleMethodReplacement(ClassFile file, ClassLoader loader, Class<?> oldClass, ClassDataBuilder builder, Set<Class<?>> superclassesToHotswap) {
        // 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);
            virtMethod.setAccessFlags(0 | AccessFlag.PUBLIC);
            if (file.isInterface()) {
                virtMethod.setAccessFlags(0 | AccessFlag.PUBLIC | AccessFlag.ABSTRACT | AccessFlag.SYNTHETIC);
            } else {
                virtMethod.setAccessFlags(0 | AccessFlag.PUBLIC | AccessFlag.SYNTHETIC);
                Bytecode b = new Bytecode(file.getConstPool(), 0, 3);
                if (BuiltinClassData.skipInstrumentation(file.getSuperclass())) {
                    b.add(Bytecode.ACONST_NULL);
                    b.add(Bytecode.ARETURN);
                } 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_STATIC_METHOD_DESCRIPTOR);
                m.setAccessFlags(AccessFlag.PUBLIC | AccessFlag.STATIC | AccessFlag.SYNTHETIC);
                b = new Bytecode(file.getConstPool(), 0, 3);
                b.add(Bytecode.ACONST_NULL);
                b.add(Bytecode.ARETURN);
                staticCodeAttribute = b.toCodeAttribute();
                m.setCodeAttribute(staticCodeAttribute);
                file.addMethod(m);

                m = new MethodInfo(file.getConstPool(), "<init>", Constants.ADDED_CONSTRUCTOR_DESCRIPTOR);
                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();
        }
        BaseClassData data = builder.getBaseData();

        Set<MethodData> methods = new HashSet<MethodData>();

        methods.addAll(data.getMethods());

        ListIterator<?> it = file.getMethods().listIterator();

        // now we iterator through all methods and constructors and compare new
        // and old. in the process we modify the new class so that is's signature
        // is exactly compatible with the old class, otherwise an
        // 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())) {

                    // if the access flags do not match then what we need to do
                    // 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));
                            // 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>")) {
                        // other methods
                        // static constructors cannot have annotations so
                        // 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;
            }
            // This is a newly added method.
            // or the visilbility has been upgraded
            // with the visiblity upgrade we just copy the method
            // so it is still in the original
            if (md == null || upgradedVisibility) {
                if ((m.getAccessFlags() & AccessFlag.STATIC) != 0) {
                    Class<?> c = addMethod(file, loader, m, builder, staticCodeAttribute, true, oldClass);
                    if (c != null) {
                        superclassesToHotswap.add(c);
                    }
                } else if ((m.getName().equals("<init>"))) {
                    addConstructor(file, loader, m, builder, constructorCodeAttribute, oldClass);
                } else if (m.getName().equals("<clinit>")) {
                    // nop, we can't change this, just ignore it
                } else {
                    Class<?> c = addMethod(file, loader, m, builder, virtualCodeAttribute, false, oldClass);
                    if (c != null) {
                        superclassesToHotswap.add(c);
                    }
                }
                if (!upgradedVisibility) {
                    it.remove();
                }
            } else if (md != null) {
                methods.remove(md);
            }
            if (upgradedVisibility && md != null) {
                methods.remove(md);
            }
        }
        // these methods have been removed, change them to throw a
        // MethodNotFoundError

        for (MethodData md : methods) {
            if (md.getType() == MemberType.NORMAL) {
                createRemovedMethod(file, md, oldClass, builder);
            }
        }

        // if we did not return from a virtual method we need to call the parent
        // method directly so to this end we append some stuff to the bottom of
        // the method declaration to propagate the call to the parent
        if (!file.isInterface()) {
            try {
                staticCodeAttribute.computeMaxStack();
                virtualCodeAttribute.computeMaxStack();
                if (constructorCodeAttribute != null) {
                    constructorCodeAttribute.computeMaxStack();
                }
                for(MethodInfo method : (List<MethodInfo>)file.getMethods()) {
View Full Code Here


        } 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);

        // now we have the static method that actually does the we-writes.
        // if this is a virtual method then we need to add another virtual method
        // with the exact signature of the existing
View Full Code Here

    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(), ca.getMaxLocals());
        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
        ManipulationUtils.add16bit(bc, offset + 3); // add the branch offset

        // 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) {
View Full Code Here

        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);
View Full Code Here

          || methodName.equals( EnhancerConstants.NEXT_GETTER_NAME )
          || methodName.equals( EnhancerConstants.NEXT_SETTER_NAME ) ) {
        continue;
      }

      final CodeAttribute codeAttr = methodInfo.getCodeAttribute();
      if ( codeAttr == null ) {
        // would indicate an abstract method, continue to next method
        continue;
      }

      try {
        final CodeIterator itr = codeAttr.iterator();
        while ( itr.hasNext() ) {
          final int index = itr.next();
          final int op = itr.byteAt( index );
          if ( op != Opcode.PUTFIELD && op != Opcode.GETFIELD ) {
            continue;
View Full Code Here

                cc[i] = classPool.get(constructor.getParameterTypes()[i].getName());
            }
            CtConstructor ctConstructor = ctClass.getDeclaredConstructor(cc);

            // Signatures names
            CodeAttribute codeAttribute = (CodeAttribute) ctConstructor.getMethodInfo().getAttribute("Code");
            if (codeAttribute != null) {
                LocalVariableAttribute localVariableAttribute = (LocalVariableAttribute) codeAttribute.getAttribute("LocalVariableTable");
                if (localVariableAttribute != null && localVariableAttribute.tableLength() >= ctConstructor.getParameterTypes().length) {
                    for (int i = 0; i < ctConstructor.getParameterTypes().length + 1; i++) {
                        String name = localVariableAttribute.getConstPool().getUtf8Info(localVariableAttribute.nameIndex(i));
                        if (!name.equals("this")) {
                            parameters.add(name);
View Full Code Here

                // Generated method, skip
                continue;
            }

            // Signatures names
            CodeAttribute codeAttribute = (CodeAttribute) method.getMethodInfo().getAttribute("Code");
            if (codeAttribute == null || javassist.Modifier.isAbstract(method.getModifiers())) {
                continue;
            }
            LocalVariableAttribute localVariableAttribute = (LocalVariableAttribute) codeAttribute.getAttribute("LocalVariableTable");
            List<T2<Integer,String>> parameterNames = new ArrayList<T2<Integer,String>>();
            if (localVariableAttribute == null || localVariableAttribute.tableLength() < method.getParameterTypes().length) {
                if(method.getParameterTypes().length > 0) {
                    continue;
                }
            } else {
                for(int i=0; i<localVariableAttribute.tableLength(); i++) {
                    if (!localVariableAttribute.variableName(i).equals("__stackRecorder")) {
                        parameterNames.add(new T2<Integer,String>(localVariableAttribute.startPc(i) + localVariableAttribute.index(i), localVariableAttribute.variableName(i)));
                    }
                }
                Collections.sort(parameterNames, new Comparator<T2<Integer,String>>() {

                    public int compare(T2<Integer, String> o1, T2<Integer, String> o2) {
                        return o1._1.compareTo(o2._1);
                    }

                });
            }
            List<String> names = new ArrayList<String>();
            for (int i = 0; i < method.getParameterTypes().length + (Modifier.isStatic(method.getModifiers()) ? 0 : 1); i++) {
                if (localVariableAttribute == null) {
                    continue;
                }
                try {
                    String name = parameterNames.get(i)._2;
                    if (!name.equals("this")) {
                        names.add(name);
                    }
                } catch (Exception e) {
                    Logger.warn(e, "While applying localvariables to %s.%s, param %s", ctClass.getName(), method.getName(), i);
                }
            }
            StringBuilder iv = new StringBuilder();
            if (names.isEmpty()) {
                iv.append("new String[0];");
            } else {
                iv.append("new String[] {");
                for (Iterator<String> i = names.iterator(); i.hasNext();) {
                    iv.append("\"");
                    String aliasedName = i.next();
                    if (aliasedName.contains("$")) {
                        aliasedName = aliasedName.substring(0, aliasedName.indexOf("$"));
                    }
                    iv.append(aliasedName);
                    iv.append("\"");
                    if (i.hasNext()) {
                        iv.append(",");
                    }
                }
                iv.append("};");
            }

            CtField signature = CtField.make("public static String[] $" + method.getName() + LocalVariablesNamesTracer.computeMethodHash(method.getParameterTypes()) + " = " + iv.toString(), ctClass);
            ctClass.addField(signature);

            // No variable name, skip...
            if (localVariableAttribute == null) {
                continue;
            }

            if (isScala(applicationClass)) {
                continue;
            }

            // OK.
            // Here after each local variable creation instruction,
            // we insert a call to play.utils.LocalVariables.addVariable('var', var)
            // without breaking everything...
            for (int i = 0; i < localVariableAttribute.tableLength(); i++) {

                // name of the local variable
                String name = localVariableAttribute.getConstPool().getUtf8Info(localVariableAttribute.nameIndex(i));

                // Normalize the variable name
                // For several reasons, both variables name and name$1 will be aliased to name
                String aliasedName = name;
                if (aliasedName.contains("$")) {
                    aliasedName = aliasedName.substring(0, aliasedName.indexOf("$"));
                }


                if (name.equals("this")) {
                    continue;
                }

                /* DEBUG
                IO.write(ctClass.toBytecode(), new File("/tmp/lv_"+applicationClass.name+".class"));
                ctClass.defrost();
                 */

                try {

                    // The instruction at which this local variable has been created
                    Integer pc = localVariableAttribute.startPc(i);

                    // Move to the next instruction (insertionPc)
                    CodeIterator iterator = codeAttribute.iterator();
                    iterator.move(pc);
                    Integer insertionPc = iterator.next();

                    Javac jv = new Javac(ctClass);

                    // Compile the code snippet
                    jv.recordLocalVariables(codeAttribute, insertionPc);
                    jv.recordParams(method.getParameterTypes(), Modifier.isStatic(method.getModifiers()));
                    jv.setMaxLocals(codeAttribute.getMaxLocals());
                    jv.compileStmnt("play.classloading.enhancers.LocalvariablesNamesEnhancer.LocalVariablesNamesTracer.addVariable(\"" + aliasedName + "\", " + name + ");");

                    Bytecode b = jv.getBytecode();
                    int locals = b.getMaxLocals();
                    int stack = b.getMaxStack();
                    codeAttribute.setMaxLocals(locals);
                    if (stack > codeAttribute.getMaxStack()) {
                        codeAttribute.setMaxStack(stack);
                    }
                    iterator.insert(insertionPc, b.get());
                    iterator.insert(b.getExceptionTable(), insertionPc);


                    // Then we need to trace each affectation to the variable
                    CodeIterator codeIterator = codeAttribute.iterator();

                    // Bon chaque instruction de cette méthode
                    while (codeIterator.hasNext()) {
                        int index = codeIterator.next();
                        int op = codeIterator.byteAt(index);

                        // DEBUG
                        // printOp(op);

                        int varNumber = -1;
                        // The variable changes
                        if (storeByCode.containsKey(op)) {
                            varNumber = storeByCode.get(op);
                            if (varNumber == -2) {
                                varNumber = codeIterator.byteAt(index + 1);
                            }
                        }

                        // Si c'est un store de la variable en cours d'examination
                        // et que c'est dans la frame d'utilisation de cette variable on trace l'affectation.
                        // (en fait la frame commence à localVariableAttribute.startPc(i)-1 qui est la première affectation
                        //  mais aussi l'initialisation de la variable qui est deja tracé plus haut, donc on commence à localVariableAttribute.startPc(i))
                        if (varNumber == localVariableAttribute.index(i) && index >= localVariableAttribute.startPc(i) && index < localVariableAttribute.startPc(i) + localVariableAttribute.codeLength(i)) {

                            jv.compileStmnt("play.classloading.enhancers.LocalvariablesNamesEnhancer.LocalVariablesNamesTracer.addVariable(\"" + aliasedName + "\", " + name + ");");

                            b = jv.getBytecode();
                            locals = b.getMaxLocals();
                            stack = b.getMaxStack();
                            codeAttribute.setMaxLocals(locals);

                            if (stack > codeAttribute.getMaxStack()) {
                                codeAttribute.setMaxStack(stack);
                            }
                            codeIterator.insert(b.get());

                        }

View Full Code Here

          || methodName.equals( EnhancerConstants.NEXT_GETTER_NAME )
          || methodName.equals( EnhancerConstants.NEXT_SETTER_NAME ) ) {
        continue;
      }

      final CodeAttribute codeAttr = methodInfo.getCodeAttribute();
      if ( codeAttr == null ) {
        // would indicate an abstract method, continue to next method
        continue;
      }

      try {
        CodeIterator itr = codeAttr.iterator();
        while ( itr.hasNext() ) {
          int index = itr.next();
          int op = itr.byteAt( index );
          if ( op != Opcode.PUTFIELD && op != Opcode.GETFIELD ) {
            continue;
View Full Code Here

            CtMethod cm = cc.getDeclaredMethod(method.getName(), pool.get(paramTypeNames));

            // 使用javaassist的反射方法获取方法的参数名
            MethodInfo methodInfo = cm.getMethodInfo();

            CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
            LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute
                    .getAttribute(LocalVariableAttribute.tag);
            if (attr == null) {
                throw new RuntimeException("class:" + clazz.getName()
                        + ", have no LocalVariableTable, please use javac -g:{vars} to compile the source file");
            }
View Full Code Here

                null,
                CtMethod.ConstParameter.string(constructor.getSignature()),
                ctClass);
            newConstructor.setBody(constructor, null);
            newConstructor.setModifiers(accessFlags);
            CodeAttribute codeAttribute = newConstructor.getMethodInfo().getCodeAttribute();
            codeAttribute.setMaxLocals(codeAttribute.getMaxLocals() + 1);
            ctClass.addConstructor(newConstructor);
            return true;
        } else {
            return false;
        }
View Full Code Here

TOP

Related Classes of javassist.bytecode.CodeAttribute

Copyright © 2018 www.massapicom. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.