JVM類加載機制

我們平時在編譯java代碼之後,會生成.class文件——字節碼文件,JVM會執行字節碼文件,JVM執行字節碼文件的過程爲下面7個階段 
1. 加載 
2. 驗證 
3. 準備 
4. 解析 
5. 初始化 
6. 使用 
7. 卸載

加載

簡單的說,就是把字節碼文件加載到內存中

 

驗證


當JVM加載完Class字節碼文件,並在方法區創建對應的Class對象之後,JVM會啓動對改字節碼流的校驗,只有符合JVM字節碼規範的文件才能被JVM正確執行,校驗過程主要爲如下:

JVM規範校驗:JVM 會對字節流進行文件格式校驗,判斷其是否符合 JVM 規範,是否能被當前版本的虛擬機處理等
代碼邏輯校驗:JVM 會對代碼組成的數據流和控制流進行校驗,確保 JVM 運行該字節碼文件後不會出現致命錯誤。比如傳參、返參是否正確等


準備


當完成字節碼的校驗之後,jvm爲類變量分配內存以及初始化,但是有下面的點需要注意

內存分配的對象
java中的變量有2種類型,分別爲類變量和類成員變量 
- 類變量:被static修飾的變量 
- 類成員變量:除了類變量的其他變量

在準備階段,jvm只會爲類變量分配內存,而不會爲類成員變量分配內存,到初始化階段纔會爲類成員變量分配內存

初始化的類型
在準備階段,jvm會爲類變量分配內存,併爲其初始化,但是這裏的初始化和我們平時理解的初始化不太一樣,這裏的初始化是指爲變量賦其類型在java中的零值,而不是用戶代碼裏面的初始值,但是如果一個變量被static final修飾的話,則會被賦予用戶所希望的值

示例:

在準備階段,jvm會爲其賦值爲0,而不是1
public static int test = 1;

在準備階段,jvm會爲其賦值1
public static final int test2 = 1;
爲什麼同樣是被static修飾,但是結果不一樣,我們可以這麼理解,在java中,被final修飾代表不可變,如果被static fianl修飾,在準備階段被賦值爲0,這樣和java裏面final的約定不一致,但是如果是賦值爲1,那麼就很合乎情理。沒有被final修飾的變量,其可能在初始化階段或者運行階段發生一系列變化,所以就沒有必要在準備階段賦予用戶所要的值。

解析


當通過準備階段之後,jvm 針對類或接口、字段、類方法、接口方法、方法類型、方法句柄和調用點限定符 7 類引用進行解析。這個階段的主要是將其在常量池中的符號引用替換成直接其在內存中的直接引用。

初始化


初始化階段,用戶定義的Java代碼才真正開始執行,jvm會根據語句的執行順序對類對象初始化,下面幾種情況會觸發初始化

jvm遇到new、getstatic、putstatic、invokestatic這4條字節碼指令,如果類沒有初始化過,就會先初始化,生成這幾條指令一般是如下場景: - new:使用new關鍵字實例化對象

getstatic/putstatic:讀取或設置一個類的靜態字段(被final修飾、已在編譯器把結果放入常量池的靜態字段除外)
invokestatic調用一個類的靜態方法
使用java.lang.reflect對類進行反射調用的時候,如果類沒初始化要先初始化

當初始化一個類的時候,如果發現其父類還沒有進行過初始化,則需要先觸發其父類的初始化
當虛擬機啓動時,用戶需要指定一個要執行的主類(包含main()方法的那個類),虛擬機會先初始化這個主類。


使用


jvm初始化完之後,就會從方法入口,執行用戶的代碼

 

卸載


當用戶程序代碼執行完畢後,JVM 便開始銷燬創建的 Class 對象,最後負責運行的 JVM 也退出內存

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