1. 程式人生 > >JAVA虛擬機器類載入過程

JAVA虛擬機器類載入過程

什麼時候進行類載入

jvm虛擬機器規範沒有強制性的規定何時需要進行類的載入,但是如果遇到了以下幾種情況的指令則強制必須立即對類進行載入

new 建立物件的時候, getstatic 讀取靜態欄位的時候, putstatic 設定靜態欄位的時候, invokestatic 呼叫類的靜態方法的時候

類載入步驟

載入 -> 連線(Linking) -> 初始化

連線細分為 驗證 -> 準備 -> 解析

載入

jvm讀取class檔案將其位元組流代表的靜態儲存結構轉換為執行時結構,在方法區中生成以class為執行時候資料訪問的入口

class檔案靜態儲存結構內容:

  1. 魔數及版本號
  2. 常量池
  3. 訪問標誌
  4. 類索引,父類索引,結構索引
  5. 欄位表
  6. 方法表
  7. 屬性表

想深入瞭解的的可以用二進位制編輯器開啟 對應的class檔案就能看到以上內容想深入瞭解的的可以用二進位制編輯器開啟 對應的class檔案就能看到以上內容

連線(Linking)

連線又分為下面幾個步驟

驗證 -> 準備 -> 解析

驗證

主要是確保class檔案的正確性符合java虛擬機器規範

準備

為類變數(static)分配記憶體並設定初始值(0值,或空串)

比如 static int a= 1; 準備階段 a = 0; 解析: 將常量池中的符號引用解析為直接引用 符號引用: 類的全限定名 比如com.test.HelloWorld,它引用都class物件不一定已經載入到了記憶體中 直接引用: 能夠直接或間接的定位到記憶體中的物件

解析

其中java虛擬機器規範也沒有強制性都要求解析發生的具體時間,意思是解析可能會在連線階段發生,也能在其它地方發生

而且虛擬機器規範強制性要求了在執行以下位元組碼指令之前必須進行解析

anewarry、checkcast、getfield、getstatic、instanceof、invokednamic、invokeinterface、invokespecial、invokestatic、invokevirtual、ldc、ldc_w、multianewarry、new、putfield、putstatic

至於這些指令對應都都是什麼意思可以去 “虛擬機器位元組碼指令表” 中查詢

初始化

在這個階段會呼叫類的方法會對類變數,靜態語句塊進行賦值 它會從父類到子類一次呼叫方法,所以最先呼叫都肯定是java.lang.Object的 如果是介面的話: 只有在父介面定義了變數都時候才會呼叫 同時如果多個執行緒對類同時初始化 只會有一個初始化成功,會有加鎖同步的進行

到此一個類就被載入進了虛擬機器,同時在方法區中以這個class為入口可以訪問它的相關資訊比如常量池。