返回顶部

收藏

使用javassist动态注入代码

更多

关于java字节码的处理,目前有很多工具,如bcel,asm。不过这些都需要直接跟虚拟机指令打交道。如果你不想了解虚拟机指令,可以采用javassist。javassist是jboss的一个子项目,其主要的优点,在于简单,而且快速。直接使用java编码的形式,而不需要了解虚拟机指令,就能动态改变类的结构,或者动态生成类。

下面通过一个简单的例子,通过javassist来实现如何动态注入代码。

假设,存在类A,如下:

public class A {
    public void method() {
        for (int i = 0; i < 1000000; i++) {
        }
        System.out.println("method1");
    }
}

测试类B如下:

public class B {
    public static void main(String[] args) {
        A a = new A();
        a.method();    
    }
}

现在想统计一下method的执行时间,

默认的实现是修改method:

 public void method() {
        long start = System.currentTimeMillis();
        for (int i = 0; i < 1000000; i++) {
        }
        System.out.println("method1");
        long end = System.currentTimeMillis();
        System.out.println(end - start);
    }

如果A的方法很多,统计方法的执行时间的代码就会相应的增加。为了减少工作量,通过动态注入代码的形式来实现。

修改B的main方法:

    public static void main(String[] args) throws Exception {
      //用于取得字节码类,必须在当前的classpath中,使用全称
        CtClass ctClass = ClassPool.getDefault().get("org.esoft.A");
         //需要修改的方法名称
        String mname = "method";        
        CtMethod mold = ctClass.getDeclaredMethod(mname);
         //修改原有的方法名称
        String nname = mname + "$impl";
        mold.setName(nname);
         //创建新的方法,复制原来的方法
        CtMethod mnew = CtNewMethod.copy(mold, mname, ctClass, null);
         //主要的注入代码
        StringBuffer body = new StringBuffer();
        body.append("{\nlong start = System.currentTimeMillis();\n");
        //调用原有代码,类似于method();($$)表示所有的参数
        body.append(nname + "($$);\n");
        body.append("System.out.println(\"Call to method "
                    + mname
                    + " took \" +\n (System.currentTimeMillis()-start) + "
                    + "\" ms.\");\n");

        body.append("}");
         //替换新方法
        mnew.setBody(body.toString());
         //增加新方法
        ctClass.addMethod(mnew);
        //类已经更改,注意不能使用A a=new A();,因为在同一个classloader中,不允许装载同一个类两次
        A a=(A)ctClass.toClass().newInstance();
        a.method();
    }

这只是简单的一个应用。javassist还提供了很多的功能,用于更改类结构。有兴趣的可以参考相关文档

标签:javassist,java,字节码

收藏

0人收藏

支持

0

反对

0

相关聚客文章
  1. weager 发表 2017-11-05 12:37:45 Integer、Long等自动拆箱类型为啥会抛NullPointerException
  2. admin 发表 2013-11-13 04:38:59 javassist这货到底干嘛的?
  3. coderbee 发表 2017-07-19 14:41:16 Javassist 字节码操作库
  4. obaby 发表 2018-01-04 08:57:51 Javassist
  5. yeseng 发表 2018-09-29 14:46:14 位运算技巧整理
  6. sulong 发表 2008-02-27 06:12:41 更改jboss默认使用的rmi端口,避免冲突
  7. dulong 发表 2018-08-03 10:49:22 一道号称“史上最难”的java面试题引发的线程安全思考
  8. sulong 发表 2009-09-26 16:31:51 漫谈PHP和Java
  9. 尖兵 发表 2018-08-05 15:59:47 [Java] 1014. Waiting in Line (30)-PAT甲级
  10. 博主 发表 2014-03-20 12:27:14 java组合实现算法
  11. 邓龙华 发表 2018-08-06 12:44:11 使用 AspectJ 实现静态 AOP
  12. woaishisi 发表 2013-02-01 05:36:24 JAVA Platform Enterprise Edition 7(JSR)

发表评论