1 Java Instrument能做什么?最大的作用?
使開(kāi)發(fā)者可以構(gòu)建一個(gè)獨(dú)立于應(yīng)用程序的代理程序Agent,用來(lái)監(jiān)控和協(xié)助運(yùn)行在JVM上的程序,更重要的是能夠替換和修改某些類(lèi)的定義怨咪;
最大的作用:可以實(shí)現(xiàn)一種虛擬機(jī)級(jí)別支持的AOP實(shí)現(xiàn)方式;
2 在JDK 1.5 润匙、1.6中惊暴,Java Instrument做了哪些變動(dòng)支持?
JDK 1.5:支持靜態(tài)Instrument趁桃,就是在JVM啟動(dòng)前靜態(tài)設(shè)置Instrument;
JDK 1.6:支持動(dòng)態(tài)Instrument肄鸽,就是在JVM啟動(dòng)后動(dòng)態(tài)設(shè)置Instrument卫病;支持本地代碼Instrument;支持動(dòng)態(tài)改變classpath典徘;
3 Java Instrument的實(shí)現(xiàn)是基于JVM哪種機(jī)制蟀苛?JVMTI是什么,可以做什么逮诲?
- 基于JVMTI代理程序帜平;
- JVMTI:一套代理程序機(jī)制,為JVM相關(guān)工具提供的本地編程接口集合梅鹦;
- JVMTI可以支持第三方工具程序以代理的方式連接和訪問(wèn)JVM裆甩,并利用JVMTI提供的豐富的編程接口,完成很多跟JVM相關(guān)的功能齐唆;
4 Instrument premain嗤栓、agentmain方法執(zhí)行時(shí)機(jī)?
- premain執(zhí)行時(shí)機(jī):在JVM啟動(dòng)時(shí),初始化函數(shù)eventHandlerVMinit會(huì)調(diào)用sun.instrument.instrumentationImpl類(lèi)的loadClassAndCallPremain方法去執(zhí)行Premain-Class指定類(lèi)的premain方法茉帅;
- agentmain執(zhí)行時(shí)機(jī):在JVM啟動(dòng)后叨叙,通過(guò)VirtualMachine附著一個(gè)Instrument,如:vm.loadAgent(jar)堪澎,會(huì)調(diào)用sun.instrument.instrumentationImpl類(lèi)的loadClassAndCallAgentmain方法去執(zhí)行Agentmain-Class指定類(lèi)的agentmain方法擂错;
5 Instrument premain、agentmain方法中兩個(gè)參數(shù)agentArgs樱蛤、inst代表什么钮呀?分別會(huì)有什么作用?
- agentArgs:代理程序命令行中輸入?yún)?shù)刹悴,隨同“-javaagent”一起傳入行楞,與main函數(shù)不同的是,這個(gè)參數(shù)是一個(gè)字符串而不是一個(gè)字符串?dāng)?shù)組土匀;
- inst:java.lang.instrument.Instrumentation實(shí)例子房,由JVM自動(dòng)傳入,集中了幾乎所有功能方法就轧,如:類(lèi)操作证杭、classpath操作等;
6 java.lang.instrument.ClassFileTransformer是什么妒御,有什么作用解愤?
- ClassFileTransformer當(dāng)中的transform方法可以對(duì)類(lèi)定義進(jìn)行操作修改;
- 在類(lèi)字節(jié)碼載入JVM前乎莉,JVM會(huì)調(diào)用ClassFileTransformer.transform方法送讲,從而實(shí)現(xiàn)對(duì)類(lèi)定義進(jìn)行操作修改,實(shí)現(xiàn)AOP功能惋啃;相對(duì)于JDK 動(dòng)態(tài)代理哼鬓、CGLIB等AOP實(shí)現(xiàn)技術(shù),不會(huì)生成新類(lèi)边灭,也不需要原類(lèi)有接口异希;
7 對(duì)于agentmain方法執(zhí)行,如何進(jìn)行動(dòng)態(tài)attach agent绒瘦?
通過(guò)VirtualMachine附著一個(gè)Instrument称簿,如:vm.loadAgent(jar);
8 META-INF/MAINFEST.MF參數(shù)清單惰帽?
- Premain-Class:指定包含premain方法的類(lèi)名憨降;
- Agent-Class:指定包含agentmain方法的類(lèi)名;
- Boot-Class-Path:指定引導(dǎo)類(lèi)加載器搜索的路徑列表善茎。查找類(lèi)的特點(diǎn)于平臺(tái)的機(jī)制失敗后券册,引導(dǎo)類(lèi)加載器會(huì)搜索這些路徑;
- Can-Redefine-Class:是否能重新定義此代理所需的類(lèi),默認(rèn)為false烁焙;
- Can-Retransform-Class:是否能重新轉(zhuǎn)換此代理所需的類(lèi)航邢,默認(rèn)為false骄蝇;
- Can-Set-Native-Method-Prefix:是否能設(shè)置此代理所需的本機(jī)方法前綴,默認(rèn)值為false九火;
9 兩個(gè)核心API ClassFileTransformer、Instrumention岔激?
- ClassFileTransformer:定義了類(lèi)加載前的預(yù)處理類(lèi);
- Instrumentation:增強(qiáng)器
(1)add/removeTransformer:添加/刪除ClasFileTransformer虑鼎;
(2)retransformerClasses:指定哪些類(lèi),在已加載的情況下炫彩,重新進(jìn)行轉(zhuǎn)換處理匾七,即觸發(fā)重新加載類(lèi)定義江兢;對(duì)于重新加載的類(lèi)不能修改舊有的類(lèi)聲明,比如:不能增加屬性杉允、不能修改方法聲明等邑贴;
(3)redefineClasses:指定哪些類(lèi),觸發(fā)重新加載類(lèi)定義叔磷,與上面不同的是不會(huì)重新進(jìn)行轉(zhuǎn)換處理痢缎,而是把處理結(jié)果bytecode直接給JVM;
(4)getAllLoadedClasses:獲取當(dāng)前已加載的Class集合世澜;
(5)getInitiatedClasses:獲取由某個(gè)特定ClassLoader加載的類(lèi)定義;
(6)getObjectSize:獲得一個(gè)對(duì)象占用的空間大惺鹚搿寥裂;
(7)appendToBootstrapClassLoaderSearch/appentToSystemClassLoaderSearch:增加BootstrapClassLoader/SystemClassLoader搜索路徑;
(8)isNativeMethodPrefixSupported/SetNativeMethodPrefix:判斷JVM是否支持?jǐn)r截Native Method案疲;
10 Java Instrument工作原理封恰?
- 在JVM啟動(dòng)時(shí),通過(guò)JVM參數(shù)-javaagent褐啡,傳入agent jar诺舔,Instrument Agent被加載;
- 在Instrument Agent 初始化時(shí),注冊(cè)了JVMTI初始化函數(shù)eventHandlerVMinit低飒;
- 在JVM啟動(dòng)時(shí)许昨,會(huì)調(diào)用初始化函數(shù)eventHandlerVMinit,啟動(dòng)了Instrument Agent褥赊,用sun.instrument.instrumentationImpl類(lèi)里的方法loadClassAndCallPremain方法去初始化Premain-Class指定類(lèi)的premain方法糕档;
- 初始化函數(shù)eventHandlerVMinit,注冊(cè)了class解析的ClassFileLoadHook函數(shù)拌喉;
- 在解析Class之前速那,JVM調(diào)用JVMTI的ClassFileLoadHook函數(shù),鉤子函數(shù)調(diào)用sun.instrument.instrumentationImpl類(lèi)里的transform方法尿背,通過(guò)TransformerManager的transformer方法最終調(diào)用我們自定義的Transformer類(lèi)的transform方法端仰;
- 因?yàn)樽止?jié)碼在解析Class之前改的,直接使用修改后的字節(jié)碼的數(shù)據(jù)流替代田藐,最后進(jìn)入Class解析荔烧,對(duì)整個(gè)Class解析無(wú)影響;
- 重新加載Class依然重新走5-6步驟坞淮;