<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    閑人野居
    好好學習,天天向上
    posts - 57,  comments - 137,  trackbacks - 0
    ??? 關于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還提供了很多的功能,用于更改類結構。有興趣的可以參考相關文檔

    posted on 2007-02-10 21:02 布衣郎 閱讀(13779) 評論(9)  編輯  收藏 所屬分類: jdk相關

    FeedBack:
    # re: 使用javassist動態注入代碼
    2007-04-19 10:06 | noname
    good!  回復  更多評論
      
    # re: 使用javassist動態注入代碼[未登錄]
    2008-04-08 19:32 | Tester
    你編譯并運行過你的代碼?   回復  更多評論
      
    # re: 使用javassist動態注入代碼[未登錄]
    2008-04-08 19:34 | Tester
    如果運行的話,

    在: A a=(A)ctClass.toClass().newInstance();上將拋出 java.lang.ClassCastException

    這是為什么呢?希望你可以解答.  回復  更多評論
      
    # re: 使用javassist動態注入代碼[未登錄]
    2008-05-12 17:25 | Tester
    http://www.csg.is.titech.ac.jp/~chiba/javassist/tutorial/tutorial.html
    上關于為什么會拋出ClassCastException講的很詳細  回復  更多評論
      
    # re: 使用javassist動態注入代碼[未登錄]
    2009-05-10 15:16 | 菜鳥
    Test.main() inserts a call to println() in the method body of say() in Hello. Then it constructs an instance of the modified Hello class and calls say() on that instance.

    Note that the program above depends on the fact that the Hello class is never loaded before toClass() is invoked. If not, the JVM would load the original Hello class before toClass() requests to load the modified Hello class. Hence loading the modified Hello class would be failed (LinkageError is thrown). For example, if main() in Test is something like this:

    public static void main(String[] args) throws Exception {
    Hello orig = new Hello();
    ClassPool cp = ClassPool.getDefault();
    CtClass cc = cp.get("Hello");
    :
    }

    then the original Hello class is loaded at the first line of main and the call to toClass() throws an exception since the class loader cannot load two different versions of the Hello class at the same time.

    If the program is running on some application server such as JBoss and Tomcat, the context class loader used by toClass() might be inappropriate. In this case, you would see an unexpected ClassCastException. To avoid this exception, you must explicitly give an appropriate class loader to toClass(). For example, if bean is your session bean object, then the following code:

    CtClass cc = ...;
    Class c = cc.toClass(bean.getClass().getClassLoader());

    would work. You should give toClass() the class loader that has loaded your program (in the above example, the class of the bean object).

    toClass() is provided for convenience. If you need more complex functionality, you should write your own class loader.

      回復  更多評論
      
    # re: 使用javassist動態注入代碼
    2009-06-12 12:04 | genle657101519
    有收獲,謝了。  回復  更多評論
      
    # re: 使用javassist動態注入代碼
    2009-08-05 19:12 | helo
    CtMethod mnew = CtNewMethod.copy(mold, mname, ctClass, null);
    應該為:CtMethod mnew = CtNewMethod.copy(mold, nname, ctClass, null);

    后面的代碼也要修改。誤人子弟,無語。。。。。  回復  更多評論
      
    # re: 使用javassist動態注入代碼[未登錄]
    2009-08-07 07:42 | joe
    @helo
    確實寫錯了  回復  更多評論
      
    # re: 使用javassist動態注入代碼
    2010-08-06 17:31 | abettor

    <2009年5月>
    262728293012
    3456789
    10111213141516
    17181920212223
    24252627282930
    31123456

    常用鏈接

    留言簿(12)

    隨筆分類(59)

    隨筆檔案(57)

    blog

    java

    uml

    搜索

    •  

    積分與排名

    • 積分 - 358015
    • 排名 - 156

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 亚洲乱码一区二区三区在线观看 | 在线观看亚洲免费视频| 91手机看片国产永久免费| 久久精品亚洲综合| 国产99视频精品免费专区| 亚洲av午夜福利精品一区| 免费成人在线视频观看| 亚洲AV无码一区二区乱孑伦AS| 免费人成激情视频在线观看冫| 亚洲精品无码mv在线观看网站 | 国产AV无码专区亚洲AV麻豆丫| 在线观看无码的免费网站| 亚洲AV无码AV男人的天堂不卡| 日韩视频免费一区二区三区| 国产亚洲精品欧洲在线观看| 亚洲精品国产自在久久| 丁香花在线观看免费观看图片| 国产亚洲A∨片在线观看| 99久久国产免费-99久久国产免费 99久久国产免费中文无字幕 | 日韩人妻一区二区三区免费| 亚洲AV无码第一区二区三区| 16女性下面无遮挡免费| 亚洲色成人WWW永久在线观看 | 久久精品国产精品亚洲人人| 美女视频黄的免费视频网页| 亚洲国产高清在线精品一区 | 一级女人18片毛片免费视频| 国产乱辈通伦影片在线播放亚洲| 日本免费A级毛一片| 亚洲人成日本在线观看| 成人精品视频99在线观看免费| 亚洲大片在线观看| 夜夜嘿视频免费看| 久久久精品视频免费观看 | 精品国产污污免费网站aⅴ| 亚洲爆乳无码专区www| 国产精品亚洲精品日韩已方| 久99久精品免费视频热77| 亚洲另类无码专区丝袜| 国产亚洲真人做受在线观看| 在线A级毛片无码免费真人 |