1. 程式人生 > >JVM類載入的過程(載入、驗證、準備、解析、初始化)

JVM類載入的過程(載入、驗證、準備、解析、初始化)

載入

載入一般可以分為顯示載入(通過Class.forName()方法載入類)和隱式載入(通過關鍵字new載入),這個過程主要完成三件事:

1.通過路徑/類全名獲取該類的class檔案的二進位制位元組流。

2.將存於class檔案中的靜態資料結構轉化成JVM方法區中執行時的資料結構。

3.在記憶體中生成一個代表這個類的java.lang.Class物件,作為資料訪問這個類的唯一入口。

驗證

這一過程確保載入的class檔案符合當前JVM規範與安全。主要包含檔案格式驗證,元資料驗證,位元組碼驗證和符號引用驗證。

準備

為靜態變數(被static修飾)分配記憶體空間,設定初始值,例如static int x = 10在此階段會被初始化為0,同理boolean型別會被初始化為false,double型別會被初始化為0.0,而引用型別會被初始化為null。有兩點需要注意:1.如果類的屬性用static final修飾,即為常量,此階段會直接被初始化為該常量,如static final int x = 10,此階段會被初始化為10;2.此處不包括例項物件,例項變數將會在物件例項化的時候隨著物件一起分配在Java堆中。

解析

這一過程中虛擬機器將常量池中的符號引用替換為直接引用,例如常量“a”會被替換為記憶體中的地址。這裡解釋一下何為符號引用,何為直接引用。符號引用以一組符號來描述所引用的目標,符號可以是任何形式的字面量,只要使用時能無歧義地定位到目標即可。直接引用可以是直接指向目標的指標、相對偏移量或是一個能間接定位到目標的控制代碼。直接引用與虛擬機器實現的記憶體相關,可以表示該引用的目標物件已經存在於記憶體中,而符號引用與虛擬機器記憶體佈局無關。

初始化

此階段才真正開始執行類中定義的Java位元組碼,不同於準備階段,這時會根據程式開發人員指定的計劃來初始化類變數和靜態資源等。大多數情形是通過執行類構造器方法clinit()方法,收集類變數的賦值動作和靜態資源合併。虛擬機器會保證clinit()方法在多執行緒併發時正確的進行上鎖和同步,如果有多個執行緒同時初始化這個類,那麼只有一個執行緒執行該初始化方法。如果該類沒有類變數賦值動作和靜態資源,則編譯器可以不為這個類生成clinit()方法。