Java 编程的动态性,第 7 部分: 用 BCEL 设计字节码
2010-03-18 00:00:00 来源:WEB开发网清单 3 是转换方法的第一段代码。可以从注释中看到,第一部分只是初始化要使用的基本 BCEL 组件,它包括用要计时方法的信息初始化一个新的 org.apache.bcel.generic.MethodGen 实例。我为这个 MethodGen 设置一个空的指令清单,在后面我将用实际的计时代码填充它。在第 2 部分,我用原来的方法创建第二个 org.apache.bcel.generic.MethodGen 实例,然后从类中删除原来的方法。在第二个 MethodGen 实例中,我只是让名字加上“$impl”后缀,然后调用 getMethod() 以将可修改的方法信息转换为固定形式的 org.apache.bcel.classfile.Method 实例。然后调用 addMethod() 以便在类中添加改名后的方法。
清单 3. 添加拦截方法
// set up the construction tools
InstructionFactory ifact = new InstructionFactory(cgen);
InstructionList ilist = new InstructionList();
ConstantPoolGen pgen = cgen.getConstantPool();
String cname = cgen.getClassName();
MethodGen wrapgen = new MethodGen(method, cname, pgen);
wrapgen.setInstructionList(ilist);
// rename a copy of the original method
MethodGen methgen = new MethodGen(method, cname, pgen);
cgen.removeMethod(method);
String iname = methgen.getName() + "$impl";
methgen.setName(iname);
cgen.addMethod(methgen.getMethod());
清单 4 给出了转换方法的下一段代码。这里的第一部分计算方法调用参数在堆栈上占用的空间。之所以需要这段代码,是因为为了在调用包装方法之前在堆栈帧上存储开始时间,我需要知道局部变量可以使用什么偏移值(注意,我可以用 BCEL 的局部变量处理得到同样的效果,但是在本文中我选择使用显式的方式)。这段代码的第二部分生成对 java.lang.System.currentTimeMillis() 的调用,以得到开始时间,并将它保存到堆栈帧中计算出的局部变量偏移处。
更多精彩
赞助商链接