Java agent又叫作Java 探針,本文將從如下四個問題出發來深刻淺出了解下Java agentjava
Java agent是在JDK1.5引入的,是一種能夠動態修改Java字節碼的技術。java類編譯以後造成字節碼被JVM執行,JVM在執行這些字節碼以前獲取這些字節碼信息,而且對這些字節碼進行修改,來完成一些額外的功能,這種就是java agent技術。框架
1.java agent可以在加載java字節碼以前進行攔截並對字節碼進行修改eclipse
2.在jvm運行期間修改已經加載的字節碼jvm
經過以上兩種就能夠實如今一些框架或是技術的採集點進行字節碼修改,能夠對應用進行監控,或是對執行指定方法或是接口時額外添加操做(打印日誌、打印方法執行時間、採集方法的入參和結果等)ide
瞭解java agent的實現原理就必須先了解java的類加載機制(還不瞭解的自行了解),這個是瞭解java agent的前提。函數
其次須要瞭解的是JVMTI以及JVMTIAgent,下面分別介紹下工具
JVMTI是JVM Tool Interface的縮寫,是JVM暴露出來給用戶擴展使用的接口集合,JVMTI是基於事件驅動的,JVM每執行必定的邏輯就會調用一些事件的回調接口,這些接口能夠給用戶自行擴展來實現本身的邏輯idea
JVMTIAgent是一個動態庫,利用JVMTI暴露出來的接口實現用戶自行的邏輯(eclipse、idea等工具等代碼調試就是經過這個實現的)spa
JVMTIAgent主要有三個方法,線程
Agent_OnLoad方法,若是agent在啓動時加載,就執行這個方法
Agent_OnAttach方法,若是agent不是在啓動的時候加載的,是咱們先attach到目標線程上,而後對對應的目標進程發送load命令來加載agent,在加載過程當中調用Agent_OnAttach函數
Agent_OnUnload方法,在agent作卸載掉時候調用
instrument agent實現了Agent_OnLoad方法和Agent_OnAttach方法,也就是即能在啓動的時候加載agent,也能夠在運行期來加動態加載agent,運行期動態加載agent依賴JVM的attach機制實現,經過發送load命令來加載agent
jvm attach機制上JVM提供的一種JVM進程間通訊的功能,能讓一個進程傳命令給另外一個進程,並進行一些內部的操做,好比進行線程dump,那麼就須要執行jstack進行,而後把pid等參數傳遞給須要dump的線程來執行,這就是一種java attach。
第一次類加載的時候要求被transform的場景,在加載類文件的時候發出ClassFileLoad事件,交給instrument agent來調用java agent裏註冊的ClassFileTransformer實現字節碼的修改
類從新定義,主要用在已經被加載的類上
原理了解清楚了就須要實現,java agent實現字節碼加強到過程大概是:
1.修改字節碼、2.加載新到字節碼、3.替換舊的字節碼
第二步能夠經過自定義ClassLoader來加載修改的字節碼,第三步能夠經過JVM加載或運行字節碼時進行替換,那麼第一步修改字節碼該如何進行呢,至少大部分人時不會修改的,那麼就須要使用工具來修改,
目前實現修改字節碼的工具主要有ASM、Javassist和byte buddy,下一篇將着重介紹這三種字節碼生成框架及用法