WEB开发网
开发学院软件开发Java 用 BCEL 设计字节码: 直接在方法的调用处添加方法... 阅读

用 BCEL 设计字节码: 直接在方法的调用处添加方法

 2009-09-23 00:00:00 来源:WEB开发网   
核心提示: main这个调用的代码或者使用INVOKEXXXX指令实现,或者把这些调用方法的字节码指令序列加入到main的指令序列当中来实现,用 BCEL 设计字节码: 直接在方法的调用处添加方法(4),直接加的话可能自己事先写的方法的局部变量与main方法的局部变量会相同,而且涉及到所加的指令序列使用局部

main这个调用的代码或者使用INVOKEXXXX指令实现,或者把这些调用方法的字节码指令序列加入到main的指令序列当中来实现,直接加的话可能自己事先写的方法的局部变量与main方法的局部变量会相同,而且涉及到所加的指令序列使用局部变量的问题,比如加的iload_0,istore_2就会引用现在方法的局部变量,但是现在的局部变量根本就不是这种指令所对应的类型

。所以还是使用方法调用比较方便

import java.io.FileOutputStream;
import org.apache.bcel.Constants;
import org.apache.bcel.classfile.ClassParser;
import org.apache.bcel.classfile.ConstantClass;
import org.apache.bcel.classfile.ConstantMethodref;
import org.apache.bcel.classfile.ConstantNameAndType;
import org.apache.bcel.classfile.ConstantPool;
import org.apache.bcel.classfile.JavaClass;
import org.apache.bcel.classfile.Method;
import org.apache.bcel.generic.ClassGen;
import org.apache.bcel.generic.ConstantPoolGen;
import org.apache.bcel.generic.INVOKEVIRTUAL;
import org.apache.bcel.generic.Instruction;
import org.apache.bcel.generic.InstructionFactory;
import org.apache.bcel.generic.InstructionHandle;
import org.apache.bcel.generic.InstructionList;
import org.apache.bcel.generic.LocalVariableGen;
import org.apache.bcel.generic.MethodGen;
import org.apache.bcel.generic.Type;

public class BCELTiming3 {
    
    
    
    /**//*
     * 扫描StringBuilder的各个方法的指令序列,在其中找Invokexxxx指令,
     * 看此指令在常量池中引用的方法引用是否是要其前后加代码的方法
     * 方法所在的类要一致,方法的名称要一致,方法的签名要一致
     * 
     */
    
    /** *//**
     * 
     * @param cgen 要被解析的类class文件
     * @param classname 要被修改的方法所在的类名称,若有包名,则为java/lang/Object类似的
     * @param methodname 要被修改的方法的名称
     * @param methodSignature 要被修改的方法的签名
     */
    private static void modifyWrapper(ClassGen cgen,String classname,String methodname,String methodSignature){
        
        InstructionFactory ifact = new InstructionFactory(cgen);
        ConstantPoolGen pgen = cgen.getConstantPool();
        ConstantPool pool = pgen.getConstantPool();
        
        String cname = cgen.getClassName();
        
        
        
        Method[] methods = cgen.getMethods();
        for(int i=0;i<methods.length;i++){
            Method tempMethod = methods[i];
            
            MethodGen tempMethodGen = new MethodGen(tempMethod,cname,pgen);
            
            InstructionList tempList = tempMethodGen.getInstructionList();
            tempList.iterator();
            Instruction[] tempInstructions = tempList.getInstructions();
            InstructionHandle[] tempInHandles = tempList.getInstructionHandles();
            for(int j=0;j<tempInHandles.length;j++){
                InstructionHandle ihandle = tempInHandles[j];
                Instruction nowInstruction = ihandle.getInstruction();
                if(nowInstruction.getOpcode()==Constants.INVOKEVIRTUAL){
                    INVOKEVIRTUAL invokeVirtual = (INVOKEVIRTUAL)nowInstruction;
                    ConstantMethodref cmr = (ConstantMethodref)pgen.getConstant(invokeVirtual.getIndex());
                    
                    ConstantClass cc = (ConstantClass)pgen.getConstant(cmr.getClassIndex());
                    String nowClassName = cc.getBytes(pgen.getConstantPool());
                    ConstantNameAndType cnt = (ConstantNameAndType)pgen.getConstant(cmr.getNameAndTypeIndex());
                    String nowMethodName = cnt.getName(pgen.getConstantPool());
                    String nowMethodSignature = cnt.getSignature(pgen.getConstantPool());
                    
                    //判断此方法的所属的类,方法的名称,方法的签名是否与所要加的一致(I)Ljava/lang/String;
                    if(nowClassName.equals(classname) && nowMethodName.equals(methodname) && nowMethodSignature.equals(methodSignature)){
                        
                        cgen.removeMethod(tempMethodGen.getMethod());
                        
                        //找到此方法在list的位置
                        InstructionList beforeList = new InstructionList();
                        //先加一个局部变量保存starttime的值
                        LocalVariableGen lvg = tempMethodGen.addLocalVariable("starttime", Type.LONG, null, null);
                        beforeList.append(ifact.createInvoke("ToolUtil", "printStart", Type.LONG, Type.NO_ARGS, Constants.INVOKESTATIC));
                        beforeList.append(InstructionFactory.createStore(Type.LONG, lvg.getIndex()));
                        tempList.insert(ihandle.getPrev().getPrev(), beforeList);
                        
                        //加方法后的代码
                        InstructionList afterList = new InstructionList();
                        afterList.append(ifact.createConstant(methodname));
                        afterList.append(ifact.createLoad(Type.LONG, lvg.getIndex()));
                        afterList.append(ifact.createInvoke("ToolUtil", "printEnd", Type.VOID, new Type[]{Type.STRING,Type.LONG}, Constants.INVOKESTATIC));
                        tempList.insert(ihandle.getNext().getNext(), afterList);
                        
                        
                        //finalize the construted method
                        tempMethodGen.stripAttributes(false);
                        tempMethodGen.setMaxStack();
                        tempMethodGen.setMaxLocals();
                        cgen.addMethod(tempMethodGen.getMethod());
                        
                        System.out.println(tempMethodGen.getInstructionList());
                        System.out.println();
                        System.out.println();
                        
                        
                    }
                }
            }
            
//            tempList.setPositions();
//            tempList.findHandle(pos);
            
        }
            
    }
    /** *//**
     * @param args
     */
    public static void main(String[] args) {
        
        args[0]="D:\\java to eclipse\\javaeclipsestudy\\workspace\\BCELTest\\bin\\StringBuilder.class";
        
        if(args.length==1 && args[0].endsWith(".class")){
            try{
                JavaClass jclas = new ClassParser(args[0]).parse();
                
                ClassGen cgen = new ClassGen(jclas);
                
                modifyWrapper(cgen,"StringBuilder","buildString","(I)Ljava/lang/String;");
                
                
                cgen.getJavaClass().dump(args[0]);
            }catch(Exception e){
                e.printStackTrace();
            }
        }else{
            System.out.println("usage: class-file");
        }
    }
}

上一页  1 2 3 4 

Tags:BCEL 设计 字节

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接