1 Java Instrument能做什麼?最大的作用?
使開發者可以構建一個獨立於應用程式的代理程式Agent,用來監控和協助執行在JVM上的程式,更重要的是能夠替換和修改某些類的定義;
最大的作用:可以實現一種虛擬機器級別支援的AOP實現方式;
2 在JDK 1.5 、1.6中,Java Instrument做了哪些變動支援?
JDK 1.5:支援靜態Instrument,就是在JVM啟動前靜態設定Instrument;
JDK 1.6:支援動態Instrument,就是在JVM啟動後動態設定Instrument;支援原生程式碼Instrument;支援動態改變classpath;
3 Java Instrument的實現是基於JVM哪種機制?JVMTI是什麼,可以做什麼?
- 基於JVMTI代理程式;
- JVMTI:一套代理程式機制,為JVM相關工具提供的本地程式設計介面集合;
- JVMTI可以支援第三方工具程式以代理的方式連線和訪問JVM,並利用JVMTI提供的豐富的程式設計介面,完成很多跟JVM相關的功能;
4 Instrument premain、agentmain方法執行時機?
- premain執行時機:在JVM啟動時,初始化函式eventHandlerVMinit會呼叫sun.instrument.instrumentationImpl類的loadClassAndCallPremain方法去執行Premain-Class指定類的premain方法;
- agentmain執行時機:在JVM啟動後,通過VirtualMachine附著一個Instrument,如:vm.loadAgent(jar),會呼叫sun.instrument.instrumentationImpl類的loadClassAndCallAgentmain方法去執行Agentmain-Class指定類的agentmain方法;
5 Instrument premain、agentmain方法中兩個引數agentArgs、inst代表什麼?分別會有什麼作用?
- agentArgs:代理程式命令列中輸入引數,隨同“-javaagent”一起傳入,與main函式不同的是,這個引數是一個字串而不是一個字串陣列;
- inst:java.lang.instrument.Instrumentation例項,由JVM自動傳入,集中了幾乎所有功能方法,如:類操作、classpath操作等;
6 java.lang.instrument.ClassFileTransformer是什麼,有什麼作用?
- ClassFileTransformer當中的transform方法可以對類定義進行操作修改;
- 在類位元組碼載入JVM前,JVM會呼叫ClassFileTransformer.transform方法,從而實現對類定義進行操作修改,實現AOP功能;相對於JDK 動態代理、CGLIB等AOP實現技術,不會生成新類,也不需要原類有介面;
7 對於agentmain方法執行,如何進行動態attach agent?
通過VirtualMachine附著一個Instrument,如:vm.loadAgent(jar);
8 META-INF/MAINFEST.MF引數清單?
- Premain-Class:指定包含premain方法的類名;
- Agent-Class:指定包含agentmain方法的類名;
- Boot-Class-Path:指定引導類載入器搜尋的路徑列表。查詢類的特點於平臺的機制失敗後,引導類載入器會搜尋這些路徑;
- Can-Redefine-Class:是否能重新定義此代理所需的類,預設為false;
- Can-Retransform-Class:是否能重新轉換此代理所需的類,預設為false;
- Can-Set-Native-Method-Prefix:是否能設定此代理所需的本機方法字首,預設值為false;
9 兩個核心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;
10 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步驟;