zoukankan      html  css  js  c++  java
  • 使用javassist动态注入代码

    关于java字节码的处理,目前有很多工具,如bcel,asm。不过这些都需要直接跟虚拟机指令打交道。如果你不想了解虚拟机指令,可以采用 javassist。javassist是jboss的一个子项目,其主要的优点,在于简单,而且快速。直接使用java编码的形式,而不需要了解虚拟机 指令,就能动态改变类的结构,或者动态生成类。
        下面通过一个简单的例子,通过javassist来实现如何动态注入代码。
        假设,存在类A,如下:
    java 代码
    1. public class A {  
    2.     public void method() {  
    3.         for (int i = 0; i < 1000000; i++) {  
    4.          }  
    5.          System.out.println("method1");  
    6.      }  
    7. }  

    测试类B如下:
    java 代码
    1. public class B {  
    2.     public static void main(String[] args) {  
    3.          A a = new A();  
    4.          a.method();     
    5.      }  
    6. }  

    现在想统计一下method的执行时间,
    默认的实现是修改method:
    java 代码
    1. public void method() {  
    2.         long start = System.currentTimeMillis();  
    3.         for (int i = 0; i < 1000000; i++) {  
    4.          }  
    5.          System.out.println("method1");  
    6.         long end = System.currentTimeMillis();  
    7.          System.out.println(end - start);  
    8.      }  

    如果A的方法很多,统计方法的执行时间的代码就会相应的增加。为了减少工作量,通过动态注入代码的形式来实现。
    修改B的main方法:
    java 代码
    1. public static void main(String[] args) throws Exception {  
    2.     //用于取得字节码类,必须在当前的classpath中,使用全称  
    3.        CtClass ctClass = ClassPool.getDefault().get("org.esoft.A");  
    4.        //需要修改的方法名称  
    5.        String mname = "method";         
    6.        CtMethod mold = ctClass.getDeclaredMethod(mname);  
    7.        //修改原有的方法名称  
    8.        String nname = mname + "$impl";  
    9.        mold.setName(nname);  
    10.        //创建新的方法,复制原来的方法  
    11.        CtMethod mnew = CtNewMethod.copy(mold, mname, ctClass, null);  
    12.        //主要的注入代码  
    13.        StringBuffer body = new StringBuffer();  
    14.        body.append("{/nlong start = System.currentTimeMillis();/n");  
    15.       //调用原有代码,类似于method();($$)表示所有的参数  
    16.        body.append(nname + "($$);/n");  
    17.        body.append("System.out.println(/"Call to method "  
    18.                    + mname  
    19.                    + " took /" +/n (System.currentTimeMillis()-start) + "  
    20.                    + "/" ms./");/n");  
    21.       
    22.        body.append("}");  
    23.        //替换新方法  
    24.        mnew.setBody(body.toString());  
    25.        //增加新方法  
    26.        ctClass.addMethod(mnew);  
    27.       //类已经更改,注意不能使用A a=new A();,因为在同一个classloader中,不允许装载同一个类两次  
    28.        A a=(A)ctClass.toClass().newInstance();  
    29.        a.method();  
    30.    }  

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

    转自:http://hi.baidu.com/winterhome/blog/item/f41314f4b2e073def2d38531.html
  • 相关阅读:
    wpf button的mouse(leftbutton)down/up,click事件不响应解决办法
    多线程引发OutOfMemoryException
    WINDBUG常用命令
    有关OEP脱壳
    reversing.kr easykeygen 之wp
    reversing.kr easy crack 之write up
    pwnable.kr leg之write up
    pwnable input2 之 write up
    pwnable.kr random 之 write up
    pwnable.kr 之 passcode write up
  • 原文地址:https://www.cnblogs.com/lanzhi/p/6469836.html
Copyright © 2011-2022 走看看