Java面試進階:類加載和雙親委派模型

類加載過程:

加載、鏈接、初始化

加載階段(Loading),它是 Java 將字節碼數據從不同的數據源讀取到 JVM 中,並映射爲 JVM 認可的數據結構(Class 對象)

鏈接(Linking),這是核心的步驟,

      驗證(Verification),這是虛擬機安全的重要保障,JVM 需要覈驗字節信息是符合 Java 虛擬機規範的

      準備(Preparation),創建類或接口中的靜態變量,並初始化靜態變量的初始值。但這裏的“初始化”和下面的顯式初始化階段                                               是有區別的,側重點在於分配所需要的內存空間,不會去執行更進一步的 JVM 指令。

      解析(Resolution),在這一步會將常量池中的符號引用(symbolic reference)替換爲直接引用

初始化階段(initialization),這一步真正去執行類初始化的代碼邏輯,包括靜態字段賦值的動作,以及執行類定義中的靜態初始化塊內的邏輯

普通原始類型靜態變量和引用類型(即使是常量),是需要額外調用 putstatic 等 JVM 指令的,這些是在顯式初始化階段執行,而不是準備階段調用;而原始類型常量,則不需要這樣的步驟。

雙親委派模型:

三個特徵:

不是所有類加載都遵守這個模型比,如 JDK 內部的 ServiceProvider/ServiceLoader機制,用戶可以在標準 API 框架上,提供自己的實現,JDK 也需要提供些默認的參考實現。 如Java 中 JNDI、JDBC、文件系統、Cipher 等很多方面,都是利用的這種機制,這種情況就不會用雙親委派模型去加載,而是利用所謂的上下文加載器。

可見性,子類加載器可以訪問父加載器加載的類型,但是反過來是不允許的

單一性,父加載器中加載過的類型,子加載器中不會重複加載。類加載器“鄰居”間,同一類型仍然可以被加載多次,因爲互相併不可見。

JDK 9看,Jigsaw 項目引入了 Java 平臺模塊化系統(JPMS)類加載器,類文件容器等都發生了非常大的變化:

擴展類加載器被重命名爲平臺類加載器,擴展的文件放入 classpath 裏;rt.jar 和 tools.jar 同樣是被移除了;增加了 Layer 的抽象, JVM 啓動默認創建 BootLayer,開發者也可以自己去定義和實例化 Layer,可以更加方便的實現類似容器一般的邏輯抽象。

 

自定義類加載器:

需求場景:兩個模塊依賴於某個類庫的不同版本,如果分別被不同的容器加載,就可以互不干擾。應用需要從不同的數據源獲取類定義信息。或者是需要自己操縱字節碼,動態修改或者生成類型(平臺化項目中有相關實現)。

過程:可參考(https://www.baeldung.com/java-classloaders

1)通過指定名稱,找到其二進制實現,在特定數據源根據名字獲取字節碼,或者修改或生成字節碼。

2)然後,創建 Class 對象,並完成類加載過程。

 

如何提高加載效率:

1)AOT,相當於直接編譯成機器碼

2)AppCDS:JVM 將類信息加載, 解析成爲元數據,將這些元數據直接存儲在文件系統中,通過內存映射技術,直接映射到相應的地址空間,免除了類加載、解析等各種開銷。

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章