Java Instrument 能做什么?最大的作用?
使開發者可以構建一個獨立於應用程序的代理程序 Agent,用來監控和協助運行在 JVM 上的程序,更重要的是能夠替換和修改某些類的定義;
最大的作用:可以實現一種虛擬機級別支持的 AOP 實現方式;
基於 JVMTI 代理程序。
JVMTI:一套代理程序機制,為 JVM 相關工具提供的本地編程接口集合。
JVMTI 可以支持第三方工具程序以代理的方式連接和訪問 JVM,並利用 JVMTI 提供的豐富的編程接口,完成很多跟 JVM 相關的功能。
java.lang.instrument.ClassFileTransformer 是什么,有什么作用?
ClassFileTransformer 當中的 transform 方法可以對類定義進行操作修改;
在類字節碼載入 JVM 前,JVM 會調用 ClassFileTransformer.transform 方法,從而實現對類定義進行操作修改,實現 AOP 功能;相對於 JDK 動態代理、CGLIB 等 AOP 實現技術,不會生成新類,也不需要原類有接口;
兩個核心 API:ClassFileTransformer、Instrumention?
ClassFileTransformer:定義了類加載前的預處理類;
Instrumentation:增強器
(1)add/removeTransformer:添加/刪除 ClasFileTransformer;
(2)retransformerClasses:指定哪些類,在已加載的情況下,重新進行轉換處理,即觸發重新加載類定義;對於重新加載的類不能修改舊有的類聲明,比如:不能增加屬性、不能修改方法聲明等;
(3)redefineClasses:指定哪些類,觸發重新加載類定義,與上面不同的是不會重新進行轉換處理,而是把處理結果 bytecode 直接給 JVM;
(4)getAllLoadedClasses:獲取當前已加載的 Class 集合;
(5)getInitiatedClasses:獲取由某個特定 ClassLoader 加載的類定義;
(6)getObjectSize:獲得一個對象占用的空間大小;
(7)appendToBootstrapClassLoaderSearch/appentToSystemClassLoaderSearch:增加 BootstrapClassLoader/SystemClassLoader 搜索路徑;
(8)isNativeMethodPrefixSupported/SetNativeMethodPrefix:判斷 JVM 是否支持攔截 Native Method;
Java Instrument 工作原理?
在 JVM 啟動時,通過 JVM 參數 -javaagent,傳入 agent jar,Instrument Agent 被加載;
在 Instrument Agent 初始化時,注冊了 JVMTI 初始化函數 eventHandlerVMinit;
在 JVM 啟動時,會調用初始化函數 eventHandlerVMinit,啟動了 Instrument Agent,用 sun.instrument.instrumentationImpl 類里的方法 loadClassAndCallPremain 方法去初始化 Premain-Class 指定類的 premain 方法;
初始化函數 eventHandlerVMinit,注冊了 class 解析的 ClassFileLoadHook 函數;
在解析 Class 之前,JVM 調用 JVMTI 的 ClassFileLoadHook 函數,鈎子函數調用 sun.instrument.instrumentationImpl 類里的 transform 方法,通過 TransformerManager 的 transformer 方法最終調用我們自定義的 Transformer 類的 transform 方法;
因為字節碼在解析 Class 之前改的,直接使用修改后的字節碼的數據流替代,最后進入 Class 解析,對整個 Class 解析無影響;
重新加載 Class 依然重新走 5-6 步驟;
