posts - 15,comments - 65,trackbacks - 0
                想必不少人聽說過javaagent,但是很少人聽說Instrumentation,其實Instrumentation就是javaagent的實現機制,說到Instrumentation,就必須想了解javaattach機制,那就先說下attach的實現。

                  大家進行jstack的時候,是不是經常看到兩個線程Signal Dispatcher Attach Listener線程,可能不知道是干嘛的吧,這兩個線程是實現attach的關鍵所在,其中前者是在jvm啟動的時候就會創建的,后者只有接收過attach請求的時候vm才會創建,顧名思義,Signal Dispatcher是分發信號的, Attach Listener 是處理attach請求的,那么兩者有什么關系呢,當我們執行attach方法的時候,會向目標vm發出一個SIGQUIT 的信號,目標vm收到這個信號之后就會創建Attach Listener線程了,當然jvm保證了不會多創建。
           1  path = findSocketFile(pid);
           2         if (path == null) {
           3             File f = new File(tmpdir, ".attach_pid" + pid);
           4             createAttachFile(f.getPath());
           5             try {
           6                 sendQuitTo(pid);
           7 
           8                 // give the target VM time to start the attach mechanism
           9                 int i = 0;
          10                 long delay = 200;
          11                 int retries = (int)(attachTimeout() / delay);
          12                 do {
          13                     try {
          14                         Thread.sleep(delay);
          15                     } catch (InterruptedException x) { }
          16                     path = findSocketFile(pid);
          17                     i++;
          18                 } while (i <= retries && path == null);
          19                 if (path == null) {
          20                     throw new AttachNotSupportedException(
          21                         "Unable to open socket file: target process not responding " +
          22                         "or HotSpot VM not loaded");
          23                 }
          24             } finally {
          25                 f.delete();
          26             }
          27         }
                  Attach機制說得簡單點就是提供A進程可以連上B進程(當然是java進程),創建socket進行通信,A通過發命令給B,B然后對命令進行截取從自己的vm中獲取信息發回給客戶端vm,但是并不是隨便發指令都會處理的,那么attach Listener接收哪些命令呢,如下所示
          static AttachOperationFunctionInfo funcs[] = {
            { "agentProperties",  get_agent_properties },
            { "datadump",         data_dump },
            { "dumpheap",         dump_heap },
            { "load",             JvmtiExport::load_agent_library },
            { "properties",       get_system_properties },
            { "threaddump",       thread_dump },
            { "inspectheap",      heap_inspection },
            { "setflag",          set_flag },
            { "printflag",        print_flag },
            { "jcmd",             jcmd },
            { NULL,               NULL }
          };
                   Instrumentation的實現其實主要使用了load這個指令,它用來實現讓target vm動態加載agentlib,Instrumentation的實現在一個名為libinstrument.dylib的動態lib庫,linux下是libinstrument.so,它是基于jvmti接口實現的,因此在對其進行load的時候會創建一個agent實例,并往jvmti環境注冊一些回調方法,比如監聽類文件加載的事件,vm初始化完成事件等,執行Agent_OnAttach,這里會創建一個Instrumentation實例并返回給用戶供大家擴展Instrumentation,比如增加一些transform。并會執行Instrumentation實例的loadClassAndCallAgentmain方法,該方法主要執行agent的MF文件里定義的 Agent-Class類的agentmain方法,當vm初始化完畢之后,會調用loadClassAndCallPremain方法,該方法主要執行agent的MF文件里定義的 Agent-Class類的pre main方法。在類進行加載的時候會調用Instrumentation的transform方法,可以看看參數里有個byte數組,這個數組其實就是正在加載的class字節碼,所以如果要字節碼增強在這里就可以入手啦,甚至可以實現偷天換日.
          posted on 2013-04-12 22:38 你假笨 閱讀(2203) 評論(0)  編輯  收藏

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


          網站導航:
           
          主站蜘蛛池模板: 泰和县| 南汇区| 北京市| 柘荣县| 峨眉山市| 东至县| 綦江县| 通辽市| 慈溪市| 锦屏县| 双江| 阜阳市| 奉贤区| 长宁区| 镇赉县| 阿合奇县| 准格尔旗| 锡林浩特市| 特克斯县| 温泉县| 青海省| 临高县| 霞浦县| 安平县| 什邡市| 汉寿县| 巍山| 新蔡县| 左权县| 九寨沟县| 望江县| 黄平县| 杂多县| 昌平区| 深圳市| 泾川县| 盖州市| 樟树市| 临邑县| 应城市| 洪湖市|