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

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

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

    閑人野居
    好好學(xué)習(xí),天天向上
    posts - 57,  comments - 137,  trackbacks - 0
    ??? 關(guān)于java字節(jié)碼的處理,目前有很多工具,如bcel,asm。不過這些都需要直接跟虛擬機(jī)指令打交道。如果你不想了解虛擬機(jī)指令,可以采用javassist。javassist是jboss的一個子項(xiàng)目,其主要的優(yōu)點(diǎn),在于簡單,而且快速。直接使用java編碼的形式,而不需要了解虛擬機(jī)指令,就能動態(tài)改變類的結(jié)構(gòu),或者動態(tài)生成類。
    ??? 下面通過一個簡單的例子,通過javassist來實(shí)現(xiàn)如何動態(tài)注入代碼。
    ??? 假設(shè),存在類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();?? ?
    ??? }
    }
    現(xiàn)在想統(tǒng)計一下method的執(zhí)行時間,
    默認(rèn)的實(shí)現(xiàn)是修改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的方法很多,統(tǒng)計方法的執(zhí)行時間的代碼就會相應(yīng)的增加。為了減少工作量,通過動態(tài)注入代碼的形式來實(shí)現(xiàn)。
    修改B的main方法:
    ??? public static void main(String[] args) throws Exception {
    ?? ?? //用于取得字節(jié)碼類,必須在當(dāng)前的classpath中,使用全稱
    ??????? CtClass ctClass = ClassPool.getDefault().get("org.esoft.A");
    ???????? //需要修改的方法名稱
    ??????? String mname = "method";?????? ?
    ??????? CtMethod mold = ctClass.getDeclaredMethod(mname);
    ???????? //修改原有的方法名稱
    ??????? String nname = mname + "$impl";
    ??????? mold.setName(nname);
    ???????? //創(chuàng)建新的方法,復(fù)制原來的方法
    ??????? CtMethod mnew = CtNewMethod.copy(mold, mname, ctClass, null);
    ???????? //主要的注入代碼
    ??????? StringBuffer body = new StringBuffer();
    ??????? body.append("{\nlong start = System.currentTimeMillis();\n");
    ??????? //調(diào)用原有代碼,類似于method();($$)表示所有的參數(shù)
    ??????? 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);
    ??????? //類已經(jīng)更改,注意不能使用A a=new A();,因?yàn)樵谕粋€classloader中,不允許裝載同一個類兩次
    ??????? A a=(A)ctClass.toClass().newInstance();
    ??????? a.method();
    ??? }
    這只是簡單的一個應(yīng)用。javassist還提供了很多的功能,用于更改類結(jié)構(gòu)。有興趣的可以參考相關(guān)文檔

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

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

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

    這是為什么呢?希望你可以解答.  回復(fù)  更多評論
      
    # re: 使用javassist動態(tài)注入代碼[未登錄]
    2008-05-12 17:25 | Tester
    http://www.csg.is.titech.ac.jp/~chiba/javassist/tutorial/tutorial.html
    上關(guān)于為什么會拋出ClassCastException講的很詳細(xì)  回復(fù)  更多評論
      
    # re: 使用javassist動態(tài)注入代碼[未登錄]
    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.

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

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

    只有注冊用戶登錄后才能發(fā)表評論。


    網(wǎng)站導(dǎo)航:
     

    <2007年2月>
    28293031123
    45678910
    11121314151617
    18192021222324
    25262728123
    45678910

    常用鏈接

    留言簿(12)

    隨筆分類(59)

    隨筆檔案(57)

    blog

    java

    uml

    搜索

    •  

    積分與排名

    • 積分 - 357208
    • 排名 - 155

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 国产免费A∨在线播放| 亚洲视频在线免费看| 亚洲AV无码欧洲AV无码网站| 久久久免费的精品| 亚洲AV一二三区成人影片| 免费欧洲毛片A级视频无风险| 中文字幕永久免费| a级毛片视频免费观看| 亚洲视频在线观看视频| 日美韩电影免费看| 青柠影视在线观看免费高清 | 无码人妻一区二区三区免费| 九九精品国产亚洲AV日韩| 亚洲热线99精品视频| 毛片免费观看视频| 91免费福利视频| 亚洲熟妇成人精品一区| 国产亚洲精品a在线观看app| 成熟女人牲交片免费观看视频 | 日韩免费电影在线观看| a毛片在线免费观看| 亚洲乱码无人区卡1卡2卡3| 久久夜色精品国产嚕嚕亚洲av| 真实乱视频国产免费观看| 国产高清不卡免费视频| 精品国产日韩亚洲一区91| 亚洲高清视频免费| 久久亚洲中文字幕精品一区| 成人毛片免费视频| 免费A级毛片无码A∨免费| 一本大道一卡二大卡三卡免费| 亚洲成_人网站图片| 亚洲精品第五页中文字幕| 亚洲国产综合无码一区| 男人的天堂亚洲一区二区三区 | 亚洲码在线中文在线观看| 亚洲中文字幕久久精品无码APP| 看全色黄大色大片免费久久 | 亚洲国产综合91精品麻豆| 亚洲国产精品日韩| 免费无码又爽又刺激毛片|