天天看點

最新版JDK15下的JVM類加載器原理詳解(下)

Bootstrap加載的路徑可以追加,不建議修改或删除原有加載路徑

在JVM中增加如下啟動參數,則能通過

Class.forName

正常讀取到指定類,說明此參數可以增加Bootstrap的類加載路徑:

-Xbootclasspath/a:/Users/sss/book/ easyCoding/byJdk11/src      

如果想在啟動時觀察加載了哪個jar包中的哪個類,可以增加

-XX:+TraceClassLoading      

此參數在解決類沖突時非常實用,畢竟不同的JVM環境對于加載類的順序并非是一緻的

有時想觀察特定類的加載上下文,由于加載的類數量衆多,調試時很難捕捉到指定類的加載過程,這時可以使用條件斷點功能

比如,想檢視HashMap的加載過程,在loadClass處打個斷點,并且在condition框内輸入如圖

最新版JDK15下的JVM類加載器原理詳解(下)

JVM如何确立每個類在JVM的唯一性

類的全限定名和加載這個類的類加載器的ID

在學習了類加載器的實作機制後,知道雙親委派模型并非強制模型,使用者可以自定義類加載器,在什麼情況下需要自定義類加載器呢?

隔離加載類

在某些架構内進行中間件與應用的子產品隔離,把類加載到不同的環境

比如,阿裡内某容器架構通過自定義類加載器確定應用中依賴的jar包不會影響到中間件運作時使用的jar包

修改類加載方式

類的加載模型并非強制,除Bootstrap外,其他的加載并非一定要引入,或者根據實際情況在某個時間點進行按需進行動态加載

擴充加載源

比如從資料庫、網絡,甚至是電視機機頂盒進行加載

防止源碼洩露

Java代碼容易被編譯和篡改,可以進行編譯加密。那麼類加載器也需要自定義,還原加密的位元組碼。

實作自定義類加載器的步驟

繼承ClassLoader

重寫findClass()方法

調用defineClass()方法

一個簡單的類加載器實作的示例代碼如下

由于中間件一般都有自己的依賴jar包,在同一個工程内引用多個架構時,往往被迫進行類的仲裁。按某種規則jar包的版本被統一指定, 導緻某些類存在包路徑、類名相同的情況,就會引起類沖突,導緻應用程式出現異常。

主流的容器類架構都會自定義類加載器,實作不同中間件之間的類隔離,有效避免了類沖突。