JVM學習(六)——JVM加載類全過程

簡介

Class 文件需要加載到虛擬機中之後才能運行和使用,系統加載 Class 類型的文件主要三步:加載->連接->初始化。連接過程又可分爲三步:驗證->準備->解析
在這裏插入圖片描述

1、加載

類加載過程的第一步,主要完成下面3件事情:

  • 通過全類名獲取定義此類的二進制字節流(得到此類的二進制字節流
  • 將字節流所代表的靜態存儲結構轉換爲方法區的運行時數據結構
  • 在內存中生成一個代表該類的 Class 對象,作爲方法區這些數據的訪問入口

加載階段和連接階段的部分內容是交叉進行的,加載階段尚未結束,連接階段可能就已經開始了。

2、驗證

  • 文件格式驗證:驗證字節流是否符合.class文件格式。
  • 元數據驗證:對字節碼中的信息進行語義分析,即有沒有語法錯誤
  • 字節碼驗證:確定程序語義是否合法
  • 符號引用驗證:確保解析後能正常運行

3、準備

準備階段是正式爲類變量分配內存設置類變量初始值的階段,這些內存都將在方法區中分配

注意:

  1. 這時候進行內存分配的僅包括類變量(static),而不包括實例變量,實例變量會在對象實例化時隨着對象一塊分配在 Java 堆中。
  2. 這裏所設置的初始值"通常情況"下是數據類型默認的零值(如0、0L、null、false等)

比如我們定義了public static int value=111 ,那麼 value 變量在準備階段的初始值就是 0 而不是111(初始化階段纔會複製)。
特殊情況:比如給 value 變量加上了 fianl 關鍵字public static final int value=111 ,那麼準備階段 value 的值就被複製爲 111。

基本數據類型的零值:
在這裏插入圖片描述

4、解析

解析階段是虛擬機將常量池內的符號引用替換爲直接引用的過程。也就是得到類或者字段、方法在內存中的指針或者偏移量。

5、初始化

初始化是類加載的最後一步,也是真正執行類中定義的 Java 程序代碼(字節碼),初始化階段是執行類構造器 < clinit> ()方法的過程。

對於< clinit>()方法的調用,虛擬機會自己確保其在多線程環境中的安全性。因爲 < clinit>()方法是帶鎖線程安全,所以在多線程環境下進行類初始化的話可能會引起死鎖,並且這種死鎖很難被發現。

對於初始化階段,虛擬機嚴格規範了有且只有5中情況下,必須對類進行初始化:

  1. 當遇到 new 等關鍵字時,初始化
  2. 使用 java.lang.reflect 包的方法對類進行反射調用時 ,如果類沒初始化,需要觸發其初始化。
  3. 初始化一個類,如果其父類還未初始化,則先觸發該父類的初始化。
  4. 當虛擬機啓動時,用戶需要定義一個要執行的主類 (包含 main 方法的那個類),虛擬機會先初始化這個類。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章