JAVA類加載器,讀完之後,大部分程序員收藏了...

一.概述

定義:

虛擬機把描述類的數據從Class文件加載到內存,並對數據進行校驗、轉換解析和初始化,最終形成可以被虛擬機直接使用的Java類型。類加載和連接的過程都是在運行期間完成的。

二. 類的加載方式

1):本地編譯好的class中直接加載

2):網絡加載:java.net.URLClassLoader可以加載url指定的類

3):從jar、zip等等壓縮文件加載類,自動解析jar文件找到class文件去加載util類

4):從java源代碼文件動態編譯成為class文件

三.類加載的時機

類加載的生命週期:加載(Loading)-->驗證(Verification)-->準備(Preparation)-->解析(Resolution)-->初始化(Initialization)-->使用(Using)-->卸載(Unloading)。如下圖所示:

JAVA類加載器,讀完之後,大部分程序員收藏了...

虛擬機規範則是嚴格規定了有且只有四種情況必須立即對類進行初始化(而加載、驗證、準備自然需要在此之前開始):

1) 遇到new 、getstatic、putstatic或invokestatic這4條字節碼指令時,如果類沒有進行初始化,則需要先觸發其初始化。生成這4條指令的最常見的java代碼場景是:使用new關鍵字實例化對象的時候、讀取或設置一個類的靜態字段(被final修飾、已在編譯器把結果放入常量池的靜態字段除外)的時候,以及調用一個類的靜態方法的時候。

2) 使用java.lang.reflect包的方法對類進行反射調用的時候,如果類沒有進行過初始化,則需要先觸發其初始化。

3) 當初始化一個類的時候,如果發現其父類還沒有進行過初始化,則需要先觸發其父類的初始化。

4) 當虛擬機啟動時,用戶需要指定一個要執行的主類(包含main()方法的那個類),虛擬機會先初始化這個主類。

可見:當滿足上述4中條件之一的任何一種情況都會執行類的靜態代碼塊,而除上述4中情況外,則不會對類的初始化(注意加粗的有且只有4個字)。

四. 類加載的過程(7個階段)

JAVA類加載器,讀完之後,大部分程序員收藏了...

4.1. 加載

a) 加載階段的工作

i. 通過一個類的全限定名來獲取定義此類的二進制字節流。

ii. 將這個字節流所代表的靜態存儲結構轉化為方法區的運行時數據結構。

iii. 在java堆中生成一個代表這個類的java.lang.Class對象,做為方法區這些數據的訪問入口。

b) 加載階段完成之後二進制字節流就按照虛擬機所需的格式存儲在方區去中。

4.2. 驗證

這一階段的目的是為了確保Class文件的字節流中包含的信息符合當前虛擬機的要求。

a) 文件格式驗證:驗證字節流是否符合Class文件格式的規範,並且能被當前版本的虛擬機處理。

b) 元數據驗證:對字節碼描述的信息進行語義分析,以確保其描述的信息符合java語言規範的要求。

c) 字節碼驗證:這個階段的主要工作是進行數據流和控制流的分析。任務是確保被驗證類的方法在運行時不會做出危害虛擬機安全的行為。

d) 符號引用驗證:這一階段發生在虛擬機將符號引用轉換為直接引用的時候(解析階段),主要是對類自身以外的信息進行匹配性的校驗。目的是確保解析動作能夠正常執行。

4.3. 準備

準備階段是正式為變量分配內存並設置初始值,這些內存都將在方法區中進行分配,這裡的變量僅包括類標量不包括實例變量。

4.4. 解析

解析是虛擬機將常量池的符號引用替換為直接引用的過程。

a) 符號引用:符號引用以一組符號來描述所引用的目標,符號可以是任意形式的字面量,只要使用時能無歧義地定位到目標即可。符號引用與虛擬機實現的內存佈局無關,引用的目標並不一定已經加載到內存中。

b) 直接引用:直接引用可以是直接指向目標的指針,相對偏移量或是一個能間接定位到目標的句柄。直接飲用是與內存佈局相關的。

c) 類或接口的解析

d) 字段的解析

e) 類方法解析

f) 接口方法解析

4.5. 初始化

是根據程序員制定的主觀計劃區初始化變量和其他資源,或者可以從另外一個角度來表達:初始化階段是執行類構造器<clinit>()方法的過程。/<clinit>

關注

感謝閱讀,如果這篇文章幫助了您,歡迎 點贊收藏,關注轉發 喲。您的幫助是我們前行的動力,我們會提供更多有價值的內容給大家... 謝謝!


分享到:


相關文章: