使開發者能夠構建一個獨立於應用程序的代理程序Agent,用來監控和協助運行在JVM上的程序,更重要的是可以替換和修改某些類的定義;java
最大的做用:能夠實現一種虛擬機級別支持的AOP實現方式;編程
JDK 1.5:支持靜態Instrument,就是在JVM啓動前靜態設置Instrument;數組
JDK 1.6:支持動態Instrument,就是在JVM啓動後動態設置Instrument;支持本地代碼Instrument;支持動態改變classpath;app
- 基於JVMTI代理程序;
- JVMTI:一套代理程序機制,爲JVM相關工具提供的本地編程接口集合;
- JVMTI能夠支持第三方工具程序以代理的方式鏈接和訪問JVM,並利用JVMTI提供的豐富的編程接口,完成不少跟JVM相關的功能;
- premain執行時機:在JVM啓動時,初始化函數eventHandlerVMinit會調用sun.instrument.instrumentationImpl類的loadClassAndCallPremain方法去執行Premain-Class指定類的premain方法;
- agentmain執行時機:在JVM啓動後,經過VirtualMachine附着一個Instrument,如:vm.loadAgent(jar),會調用sun.instrument.instrumentationImpl類的loadClassAndCallAgentmain方法去執行Agentmain-Class指定類的agentmain方法;
- agentArgs:代理程序命令行中輸入參數,隨同「-javaagent」一塊兒傳入,與main函數不一樣的是,這個參數是一個字符串而不是一個字符串數組;
- inst:java.lang.instrument.Instrumentation實例,由JVM自動傳入,集中了幾乎全部功能方法,如:類操做、classpath操做等;
- ClassFileTransformer當中的transform方法能夠對類定義進行操做修改;
- 在類字節碼載入JVM前,JVM會調用ClassFileTransformer.transform方法,從而實現對類定義進行操做修改,實現AOP功能;相對於JDK 動態代理、CGLIB等AOP實現技術,不會生成新類,也不須要原類有接口;
經過VirtualMachine附着一個Instrument,如:vm.loadAgent(jar);函數
- Premain-Class:指定包含premain方法的類名;
- Agent-Class:指定包含agentmain方法的類名;
- Boot-Class-Path:指定引導類加載器搜索的路徑列表。查找類的特色於平臺的機制失敗後,引導類加載器會搜索這些路徑;
- Can-Redefine-Class:是否能從新定義此代理所需的類,默認爲false;
- Can-Retransform-Class:是否能從新轉換此代理所需的類,默認爲false;
- Can-Set-Native-Method-Prefix:是否能設置此代理所需的本機方法前綴,默認值爲false;
- ClassFileTransformer:定義了類加載前的預處理類;
- Instrumentation:加強器
(1)add/removeTransformer:添加/刪除ClasFileTransformer;工具
(2)retransformerClasses:指定哪些類,在已加載的狀況下,從新進行轉換處理,即觸發從新加載類定義;對於從新加載的類不能修改舊有的類聲明,好比:不能增長屬性、不能修改方法聲明等;spa
(3)redefineClasses:指定哪些類,觸發從新加載類定義,與上面不一樣的是不會從新進行轉換處理,而是把處理結果bytecode直接給JVM;命令行
(4)getAllLoadedClasses:獲取當前已加載的Class集合;代理
(5)getInitiatedClasses:獲取由某個特定ClassLoader加載的類定義;code
(6)getObjectSize:得到一個對象佔用的空間大小;
(7)appendToBootstrapClassLoaderSearch/appentToSystemClassLoaderSearch:增長BootstrapClassLoader/SystemClassLoader搜索路徑;
(8)isNativeMethodPrefixSupported/SetNativeMethodPrefix:判斷JVM是否支持攔截Native Method;
- 在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步驟;