E81086713E446D36F62B2AA2A3502B5EB155

          Java雜家

          雜七雜八。。。一家之言

          BlogJava 首頁 新隨筆 聯(lián)系 聚合 管理
            40 Posts :: 1 Stories :: 174 Comments :: 0 Trackbacks

          當(dāng)你要調(diào)試一個(gè)程序時(shí),如果能把你的Java代碼注入到目標(biāo)程序并運(yùn)行,這可能會(huì)給你的調(diào)試開發(fā)帶來很大的方便,比如打印出一些全局變量值,屬性等。
          本人出于興趣,封裝了一個(gè)簡單的Java庫,可以達(dá)到這個(gè)目的。

          這個(gè)庫主要的API如下

          1 public ? class ?com.yovn.labs.vmattach.VMTool
          2 {
          3 ????? public ? static ? void ?attachJarToVM(String?pid,String?jarPath,String?mainClassToRun) throws ???AttachException
          4
          5 }

          第一個(gè)參數(shù): 你要注入的Java程序的PID
          第二個(gè)參數(shù): 你要把那個(gè)jar文件(最好用路徑全名)注入到目標(biāo)程序
          第三個(gè)參數(shù): 注入目標(biāo)程序后運(yùn)行你指定的那個(gè)Class(全名)

          該庫可以從這里下載:http://www.aygfsteel.com/Files/javacap/VMAttach.zip

          具體有什么用呢?這個(gè)看使用者怎么用,下面我弄個(gè)簡單的例子。
          加入一個(gè)程序使用一些Singleton對(duì)象,并且已經(jīng)部署并運(yùn)行了,現(xiàn)在我可能要查看一下這個(gè)Singleton對(duì)象的一些內(nèi)部狀態(tài)。

          比如,這個(gè)程序如下:

          ?1 package ?test;?
          ?2
          ?3 import ?java.util.Random;?
          ?4
          ?5 /**
          ?6 ?*? @author ?yovn
          ?7 ?*
          ?8 ? */

          ?9 public ? class ?UseSingletonApp? {?
          10
          11 ? /**
          12 ??*? @param ?args
          13 ?? */

          14 ? public ? static ? void ?main(String[]?args)? {
          15 ??
          16 ?? new ?Thread(Singleton.getInstance()).start();
          17 ???
          18
          19 ?}

          20 ? public ? static ? class ?Singleton? implements ?Runnable
          21 ? {
          22 ?? private ? final ? static ?Singleton?instance = new ?Singleton();
          23 ?? private ? volatile ? int ?stateNum;
          24 ??
          25 ??
          26 ?? private ?Singleton()
          27 ?? {
          28 ???
          29 ??}

          30 ?? public ? static ?Singleton?getInstance()
          31 ?? {
          32 ??? return ?instance;
          33 ??}

          34 ?? public ? void ?run()? {
          35 ??? while ( true )
          36 ??? {
          37 ????stateNum = new ?Random().nextInt();
          38 ???? try ? {
          39 ?????Thread.sleep( 1000 );
          40 ????}
          ? catch ?(InterruptedException?e)? {
          41 ????? // ?TODO?Auto-generated?catch?block
          42 ?????e.printStackTrace();
          43 ????}

          44 ???}

          45 ???
          46 ??}

          47 ??
          48 ?}
          ?
          49
          50 }

          51
          52


          現(xiàn)在啟動(dòng)這個(gè)Java程序,在命令行窗口運(yùn)行tasklist查看它的PID,假如為3020。
          現(xiàn)在加入我要知道這個(gè)程序現(xiàn)在的Singleton 對(duì)象的stateNum值為多少,該怎么辦呢?
          我們以前一般要以debug模式啟動(dòng),然后查看變量,難道正常啟動(dòng)就沒辦法了?
          當(dāng)然有,我們可以寫個(gè)程序,注入到目標(biāo)進(jìn)程然后打印出來,不就OK.

          當(dāng)然,這里有個(gè)問題,注入的java程序是單獨(dú)在一個(gè)線程里跑的,它的Context Class Loader是沒有設(shè)置的,你要采取一些措施才能找到目標(biāo)進(jìn)程已經(jīng)載入的class,請(qǐng)看下面的代碼:

          ?1?package?test;?
          ?2?
          ?3?import?java.lang.reflect.Field;
          ?4?import?java.lang.reflect.Method;?
          ?5?
          ?6?/**
          ?7??*?@author?yovn
          ?8??*
          ?9??*/
          10?public?class?AttachDemo?{?
          11?
          12??/**
          13???*?@param?args
          14???*/
          15??public?static?void?main(String[]?args)?{
          16???try?{
          17????Class?cls=null;//the?class?we?try?to?load?that?alrady?loaded?by?target?process
          18????
          19????//following?code?iterate?the?thread?tree,to?use?every?one?context?class?loader?to?load?the?class?util?success
          20????ThreadGroup?group?=?Thread.currentThread().getThreadGroup();
          21????while?(group?!=?null)?{
          22?????int?tc?=?group.activeCount();
          23?????Thread[]?ts?=?new?Thread[tc];
          24?????group.enumerate(ts);
          25?????for?(int?i?=?0;?i?<?tc;?i++)?{
          26??????if?(ts[i]?!=?null)?{
          27???????try{
          28????????cls=ts[i].getContextClassLoader().loadClass("test.UseSingletonApp$Singleton");
          29???????Thread.currentThread().setContextClassLoader(ts[i].getContextClassLoader());
          30???????break;
          31???????}catch(Exception?e){}
          32???????
          33??????}
          34?????}
          35?????group?=?group.getParent();
          36????}
          37????if(cls==null)
          38????{
          39?????System.out.println("can?not?load?class");
          40?????return;
          41????}
          42????Field?f?=?cls.getDeclaredField("stateNum");
          43????f.setAccessible(true);
          44????Method?getInM?=?cls.getMethod("getInstance",?new?Class[]?{});
          45????Object?singleton?=?getInM.invoke(null,?new?Object[]?{});//get?the?singleton?object
          46????
          47????int?stateNum?=?((Integer)?f.get(singleton)).intValue();
          48????System.out.println("Singleton's?stateNum?currently?is?:"?+?stateNum);
          49???}?catch?(Exception?e)?{
          50????e.printStackTrace();
          51???}?
          52?
          53??}?
          54?
          55?}
          56?
          57?


          現(xiàn)在,你需要把test.AttachDemo類編譯好,單獨(dú)打包到一個(gè) jar文件,比如d:盤的attachdemo.jar里。
          上面準(zhǔn)備好了,你就差注入attachdemo.jar到目標(biāo)進(jìn)程3020了,
          如下代碼就可以完成注入:

          ?1?import?com.yovn.labs.vmattach.AttachException;
          ?2?import?com.yovn.labs.vmattach.VMTool;?
          ?3?
          ?4?public?class?Test?{
          ?5?/**
          ?6???*?@param?args
          ?7???*?@throws?AttachException?
          ?8???*/
          ?9??public?static?void?main(String[]?args)?throws?AttachException?{
          10???VMTool.attachJarToVM("3020",?"D:\\attachdemo.jar",?"test.AttachDemo");
          11??}?
          12?
          13?}
          14?
          15?



          運(yùn)氣不錯(cuò)的話,你就能在運(yùn)行UseSingletonApp程序的命令窗口輸出類似:
          Singleton's stateNum currently is :1630285997



          總結(jié):
          目前還不是很完善,只能attach一次,稍后我會(huì)完善這個(gè)功能。另外就是只支持Window 2000/NT/XP/2003 ,Windows98不支持,Linux/Unix也是還不支持的。

          posted on 2007-01-04 13:52 DoubleH 閱讀(6172) 評(píng)論(4)  編輯  收藏

          Feedback

          # re: 運(yùn)行時(shí)注入你的Java代碼到一個(gè)已經(jīng)在運(yùn)行的Java程序 2007-01-04 14:18 BeanSoft
          是用的 JDK 1.6 才能支持吧? 呵, 無源碼.. JVMTI 之類的  回復(fù)  更多評(píng)論
            

          # re: 運(yùn)行時(shí)注入你的Java代碼到一個(gè)已經(jīng)在運(yùn)行的Java程序 2007-01-04 14:23 Javacap
          @BeanSoft
          不是,JDK6里的Attach API估計(jì)不是這樣實(shí)現(xiàn)的。它可能在新的JVM里開了什么服務(wù)程序,但是支持多平臺(tái),我這個(gè)目前只能是 Windows, 但是對(duì)JDK沒什么要求,只要JDK1.2以上就可以了。  回復(fù)  更多評(píng)論
            

          # re: 運(yùn)行時(shí)注入你的Java代碼到一個(gè)已經(jīng)在運(yùn)行的Java程序 2007-01-05 11:17 iNeo
          不錯(cuò).對(duì)于一個(gè)WEB服務(wù)來說,如果能在某個(gè)業(yè)務(wù)邏輯運(yùn)行時(shí)截獲該程序,并讀取該程序的相關(guān)參數(shù)的話,用來排錯(cuò)很有用.  回復(fù)  更多評(píng)論
            

          # re: 運(yùn)行時(shí)注入你的Java代碼到一個(gè)已經(jīng)在運(yùn)行的Java程序 2015-04-07 14:53 ww
          wroker.dll 和 vmattach.dll有源碼嗎?求分享  回復(fù)  更多評(píng)論
            


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


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 六枝特区| 克东县| 西华县| 积石山| 和田县| 庆云县| 二手房| 抚顺市| 大姚县| 寻甸| 南皮县| 公主岭市| 肥城市| 开化县| 祁东县| 娄底市| 新乡县| 南通市| 夏津县| 昌江| 永胜县| 班戈县| 乡城县| 九江市| 报价| 溆浦县| 德令哈市| 娄烦县| 璧山县| 双城市| 原阳县| 贡嘎县| 苍南县| 色达县| 手游| 安国市| 孟津县| 英德市| 彩票| 闵行区| 海阳市|