快速业务通道

Java编程的动态性,第7部分: 用BCEL设计字节码 - 编程入门网

作者 佚名技术 来源 NET编程 浏览 发布时间 2012-06-17
{        result += (char)(i%26 + ''a'');      }      return result;    }    private String buildString(int length) {      long start = System.currentTimeMillis();      String result = buildString$impl(length);      System.out.println("Call to buildString$impl took " +        (System.currentTimeMillis()-start) + " ms.");      return result;    }    public static void main(String[] argv) {      StringBuilder inst = new StringBuilder();      for (int i = 0; i < argv.length; i++) {        String result = inst.buildString(Integer.parseInt(argv [i]));        System.out.println("Constructed string of length " +          result.length());      }    } }

Java编程的动态性,第7部分: 用BCEL设计字节码(3)

时间:2011-04-09 IBM Dennis M. Sosnoski

编写转换代码

用我在 BCEL 类访问一节中描述的 BCEL API 实现添加方法计时的代码。在 JVM 指令级 别上的操作使代码比 第 4 部分 中 Javassist 的例子要长得多,所以这里我准备在提供完 整的实现之前,一段一段地介绍。在最后的代码中,所有片段构成一个方法,它有两个参数 : cgen ——它是 org.apache.bcel.generic.ClassGen 类的一个实例,用被修改的类的现 有信息初始化,和方法——要计时方法的 org.apache.bcel.classfile.Method 实例。

清单 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() 的调用,以得到开始时间,并将它保存到堆栈帧中 计算出的局部变量偏移处。

您可能会奇怪为什么在开始参数大小计算时要检查方法是否是静

凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

分享到: 更多

Copyright ©1999-2011 厦门凌众科技有限公司 厦门优通互联科技开发有限公司 All rights reserved

地址(ADD):厦门软件园二期望海路63号701E(东南融通旁) 邮编(ZIP):361008

电话:0592-5908028 传真:0592-5908039 咨询信箱:web@lingzhong.cn 咨询OICQ:173723134

《中华人民共和国增值电信业务经营许可证》闽B2-20100024  ICP备案:闽ICP备05037997号