Instrumentation介面設計初衷是為了收集Java程式執行時的資料,用於監控執行程式狀態,記錄日誌,分析程式碼用的。接下來從原始碼的流程來介紹一下
![Java Agent入門實戰(二)-Instrumentation原始碼概述](https://i.iter01.com/images/aa9eaa723f7799ac4d12c29882190a9b66520b75473c02d445cd55dd2240fccd.png)
實現類InstrumentationImpl的void addTransformer(ClassFileTransformer transformer, boolean canRetransform);
![Java Agent入門實戰(二)-Instrumentation原始碼概述](https://i.iter01.com/images/eb4c1e97ff5926ab9ff145d260d40e286033933821552c15b9df6e95215f2c13.png)
從這段程式碼知道,轉換器ClassFileTransformer的實現是儲存在TransformerManager的TransformerInfo陣列中的,陣列初始長度為0,每新增一個,陣列長度為原來的長度+1,將原陣列內容拷貝到新陣列中。
![Java Agent入門實戰(二)-Instrumentation原始碼概述](https://i.iter01.com/images/51bb406f3f1546cb9180fc27cc6a088664fae703550ff1e5637880831ae46d44.png)
VirtualMachine.attach
![Java Agent入門實戰(二)-Instrumentation原始碼概述](https://i.iter01.com/images/61d55f447b9bda0b0ff25c02687caf28b21dbde41677f2fa559a6d056da37239.png)
進入AttachProvider.providers()
,這裡面會初始化AttachProvider
,並返回一個AttachProvider List
。
![Java Agent入門實戰(二)-Instrumentation原始碼概述](https://i.iter01.com/images/98da0af5338d00b44e8937875fad9db857d9eba47f04676e977d2628daf6eb07.png)
進入ServiceLoader.load(AttachProvider.class, AttachProvider.class.getClassLoader());
![Java Agent入門實戰(二)-Instrumentation原始碼概述](https://i.iter01.com/images/a7e2c4d2471a2611404916746ecb9a9eb6b5e81216603aa716ef594c3807684f.png)
![Java Agent入門實戰(二)-Instrumentation原始碼概述](https://i.iter01.com/images/4ea20f4f3b741dfa678c78501ff7de26ba98a2222ae83ed3aaf0334ee0de865e.png)
繼續跟進方法 new LazyIterator(service, loader)
![Java Agent入門實戰(二)-Instrumentation原始碼概述](https://i.iter01.com/images/1623fbb37a961b164468e70f7165c94decef9733a7665e04b6e10d0d79535cac.png)
看一下com.sun.tools
jar包下的META-INF/services/
目錄,開啟 com.sun.tools.attach.spi.AttachProvider
,
可以看到有不同平臺作業系統的實現,我的是windows,會呼叫windos的實現sun.tools.attach.WindowsAttachProvider
。其他的都被註釋掉了。程式碼看到這,就知道ServiceLoader.load方法最終載入的是sun.tools.attach.WindowsAttachProvider
。
![Java Agent入門實戰(二)-Instrumentation原始碼概述](https://i.iter01.com/images/04a4824239bc202757eb13d80e53febd5704e8c6bf21b138bb208e9d329da539.png)
![Java Agent入門實戰(二)-Instrumentation原始碼概述](https://i.iter01.com/images/d445dfda849dbfedc59ecc5a474a4909db5873c1a3ba238e78b36ba4d47f2dcc.png)
上文hasNextService()
方法下面的nextService()
![Java Agent入門實戰(二)-Instrumentation原始碼概述](https://i.iter01.com/images/a654e1399dad923f3c0a565786912f4f90c9188b91cbcb0ee467681ca3130173.png)
回到最初的VirtualMachine.attach(String var0)
方法,進入return var4.attachVirtualMachine(var0);
的attachVirtualMachine()
內
![Java Agent入門實戰(二)-Instrumentation原始碼概述](https://i.iter01.com/images/a3c39280ae8339b3185373b05317324e84a140b8a0b0c71aedacfbf422fafcc6.png)
![Java Agent入門實戰(二)-Instrumentation原始碼概述](https://i.iter01.com/images/ff1c102632e229aeef28c19a490d736f837308a4ea2dcf3a80c37900ba2a3594.png)
![Java Agent入門實戰(二)-Instrumentation原始碼概述](https://i.iter01.com/images/79bc19361a99290141dcc07e2d3aae9664474f3cbd408badc071d800baefa35b.png)
通過 ClassLoader 類中的findNative
方法,可以找到JVM原始碼中的一些native方法呼叫名,這樣可以關聯著JVM原始碼看底層的C++原始碼到底做了啥
![Java Agent入門實戰(二)-Instrumentation原始碼概述](https://i.iter01.com/images/953a8a1302a3c075db585c1a61367f4663446853ff4cfa868350258f37c020fe.png)
發現在attach.dll中找方法名為Java_sun_tools_attach_WindowsVirtualMachine_openProcess
native method
![Java Agent入門實戰(二)-Instrumentation原始碼概述](https://i.iter01.com/images/afa6aeb0fb8335b0e1b592d0477423d8528dccc3f5880b4e6b7c0ad1719fa477.png)
嘗試性的在jdk原始碼裡去找這2個方法Java_sun_tools_attach_WindowsVirtualMachine_openProcess
和Java_sun_tools_attach_WindowsVirtualMachine_enqueue
![Java Agent入門實戰(二)-Instrumentation原始碼概述](https://i.iter01.com/images/cef0e1256a39002b8d4781e7d695f392d50fda503c801f230cf14984991cfb41.png)
![Java Agent入門實戰(二)-Instrumentation原始碼概述](https://i.iter01.com/images/0221c1da1a3b1e71fb0ca1c99a705e35a197ebe2f7b4ace50b7a805259789688.png)
virtualMachine.loadAgent()、 virtualMachine.detach()
原始碼流程和上述類似,也和平臺相關,這裡就不在贅述了。
RedefineClasse配置注意事項
可以在執行期對已載入類的位元組碼做變更,但是這種情況下會有很多的限制 對比新老類,並要求如下:
- 父類是同一個
- 實現的介面數也要相同,並且是相同的介面
- 類訪問符必須一致
- 欄位數和欄位名要一致
- 新增的方法必須是 private static/final 的
- 可以刪除修改方法
參考
點關注,不迷路
文章每週持續更新,可以微信搜尋「 十分鐘學程式設計 」第一時間閱讀和催更,如果這個文章寫得還不錯,覺得有點東西的話 ~求點贊? 求關注❤️ 求分享❤️
各位的支援和認可,就是我創作的最大動力,我們下篇文章見!
![](https://i.iter01.com/images/c6acccdd47dd8b364c58d9c6cb187f2f0f47facd19b10648b2c12e3d39fd6a49.png)