深入淺出Java類加載過程


學習筆記二之Java虛擬機中類加載的過程

當程序要使用某個類時,如果該類還未被加載到內存中,則系統會通過加載,連接,初始化三步來實現這個類進行初始化。

1.    加載

加載,是指Java虛擬機查找字節流(查找.class文件),並且根據字節流創建java.lang.Class對象的過程。這個過程,將類的.class文件中的二進制數據讀入內存,放在運行時區域的方法區內。然后在堆中創建java.lang.Class對象,用來封裝類在方法區的數據結構。

類加載階段:

(1)Java虛擬機將.class文件讀入內存,並為之創建一個Class對象。

(2)任何類被使用時系統都會為其創建一個且僅有一個Class對象。

(3)這個Class對象描述了這個類創建出來的對象的所有信息,比如有哪些構造方法,都有哪些成員方法,都有哪些成員變量等。

Student類加載過程圖示:

 

2.    鏈接

鏈接包括驗證、准備以及解析三個階段。

(1)驗證階段。主要的目的是確保被加載的類(.class文件的字節流)滿足Java虛擬機規范,不會造成安全錯誤。

(2)准備階段。負責為類的靜態成員分配內存,並設置默認初始值。

(3)解析階段。將類的二進制數據中的符號引用替換為直接引用。

說明:

符號引用。即一個字符串,但是這個字符串給出了一些能夠唯一性識別一個方法,一個變量,一個類的相關信息。

直接引用。可以理解為一個內存地址,或者一個偏移量。比如類方法,類變量的直接引用是指向方法區的指針;而實例方法,實例變量的直接引用則是從實例的頭指針開始算起到這個實例變量位置的偏移量。

舉個例子來說,現在調用方法hello(),這個方法的地址是0xaabbccdd,那么hello就是符號引用,0xaabbccdd就是直接引用。

在解析階段,虛擬機會把所有的類名,方法名,字段名這些符號引用替換為具體的內存地址或偏移量,也就是直接引用。

3.    初始化

初始化,則是為標記為常量值的字段賦值的過程。換句話說,只對static修飾的變量或語句塊進行初始化。

如果初始化一個類的時候,其父類尚未初始化,則優先初始化其父類。

如果同時包含多個靜態變量和靜態代碼塊,則按照自上而下的順序依次執行。

4.    小結

類加載過程只是一個類生命周期的一部分,在其前,有編譯的過程,只有對源代碼編譯之后,才能獲得能夠被虛擬機加載的字節碼文件;在其后還有具體的類使用過程,當使用完成之后,還會在方法區垃圾回收的過程中進行卸載(垃圾回收)。

5.    附錄

常見問題:在自己的項目里新建一個java.lang包,里面新建了一個String類,能代替系統String嗎?

不能,因為根據類加載的雙親委派機制,會將請求轉發給父類加載器,父類加載器發現沖突了String就不會加載了。

6.    參考

【1】 周志明. 深入理解Java虛擬機:JVM高級特性與最佳實踐(第二版)【M】.北京:機械工業出版社,2013  

【2】愛飛翔,周志明(譯).Java虛擬機規范(Java SE 8版)【M】.北京:機械工業出版社,2015.

【3】https://blog.csdn.net/ln152315/article/details/79223441

【4】https://blog.csdn.net/sinat_38259539/article/details/71794617


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM