JVM類加載機制

jvm的類加載機制

一.類加載的時機

類從被加載到虛擬機內存中開始,到卸載出內存爲止,他的整個生命週期包括了:加載,驗證,準備,解析,初始化,使用和卸載七個階段。其中驗證,準備和解析三個部分統稱爲鏈接。java

加載,驗證,準備,初始化和卸載這五個階段的順序是肯定的,而解析階段不必定:它在某些狀況下能夠在初始化階段以後再開始,這是爲了支持java的動態綁定。安全

注意:數據結構

1.加載。虛擬機規範中並無進行強制約束,這點能夠交給虛擬機的具體實現來自由把握。可是對於初始化階段,虛擬機規範嚴格規定了有且只有四種狀況必須當即對類進行初始化(而加載,驗證,準備最天然須要在此以前開始)jvm

狀況1:遇到new,getstatic,putstatic或invokestatic這4條字節碼指令時,若是類沒有進行過初始化,則須要先出發初始化(對應場景就是使用new實例化對象的時候,讀取或設置一個類的靜態字段(被final對象

修飾,已在編譯期把結果放入常量池的靜態字段除外)的時候,以及調用一個類的靜態方法的時候)。blog

狀況2:使用java.lang.reflect包的方法對類進行反射調用的時候生命週期

狀況3:當初始化一個類的時候,若是發現其父類尚未進行過初始化,則須要先觸發其父類的初始化。內存

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

上面這4種狀況的行爲稱爲對一個類進行主動引用。除此以外全部引用類的防暑,都不會觸發初始化,稱爲被動引用。虛擬機

二.類加載的過程

(1).加載

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

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

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

(2).驗證

驗證時鏈接階段的第一步,這一階段的目的是爲了確保Class文件的字節流包含的信息符合當前虛擬機的要求,而且不危害虛擬機自身的安全。

檢驗的過程包括文件格式驗證,元數據驗證,字節碼驗證和符號引用驗證。

1.文件格式驗證

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

2.元數據驗證

對字節碼描述的信息進行語義分析,以保證其描述的信息符合java語言規範的要求。

3.字節碼驗證

整個驗證過程當中最複雜的一個階段,主要工做是進行數據流和控制流分析。

4.符號引用驗證

將符號引用轉化爲直接引用,這個轉化動做將在鏈接的第三個階段--解析階段發生。

(3)準備

該階段是正式爲類變量分配內存並設置類變量初始值的階段,這些內存都將在方法區中進行分配。值得注意的是,這裏的內存分配的僅包括類變量(被static修飾的變量),而不包括實例變量,實例變量

將在對象實例化時隨着對象一塊兒分配在java堆裏。其次就是這裏說的初始值「一般狀況」下時數據類型的零值,假設一個類變量的定義爲:

public static int value = 123;

那麼變量value正在準備階段事後的初始值是0,而不是123,由於這時候還沒有開始執行任何Java方法,而把value賦值爲123的putstatic指令是程序被編譯後,存放在類構造器<clinit>()方法中,因此把value賦值爲123動做將在初始化階段才被執行。

相對的也會有一些"特殊狀況":若是類字段的字段屬性表中存在ConstantValue屬性,那在準備階段變量value就會被初始化爲ConstantValue屬性所指定的值,好比上面的value賦值爲123。

(4)解析

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

(5)初始化

到了初始化階段,才真正開始執行類中定義的java程序代碼

三.類加載器

雙親委派模型可以保證加載的類都是同一個,另外也有三個破壞雙親委派的地方須要注意!

相關文章
相關標籤/搜索