技術問答集錦(11)JVM類載入

猿碼道發表於2018-03-21

1 類載入機制概念是什麼?

JVM把描述類的資料從Class檔案載入到記憶體,並對資料進行校驗、轉換解析和初始化,最終形成可以被虛擬機器直接使用的Java型別。這就是類載入機制。

2 類位元組碼有哪幾部分內容組成?

Class檔案結構中只有兩種資料型別:

  1. 無符號數:屬於基本的資料型別,以u1、u2、u4、u8分別代表1、2、4、8個位元組的無符號數,可以用來描述數字、索引引用、數量值、或者按照UTF-8編碼的字串值;
  2. :由多個無符號數或者其他表作為資料項構成的複合資料型別,所有表都習慣以"_info"結尾;
  3. 所以,Class檔案本質上就是一張表;

Class檔案結構的內容組成:

  1. 魔數:每個Class檔案的前4個位元組,JAVA語言魔數:CAFEBABE,16進位制數,唯一左右就是確認檔案是否是一個被虛擬機器接受的Class檔案;
  2. Class檔案版本:Class檔案第5、6個位元組是次版本號,7、8個位元組是主版本號;
  3. 常量池:從第9個位元組開始,主要存放兩大類常量:(1)字面量;(2)符號引用;
  4. 訪問標誌:緊跟常量池之後的兩個位元組代表訪問標誌,代表類或介面的層次資訊;
  5. 類索引、父類索引與介面索引集合:緊跟訪問標誌之後的就是類索引、父類索引與介面索引,都是u2型別資料,Class檔案中由這三項資料來確定類的繼承關係;
  6. 欄位表集合:緊接著就是欄位表集合,用於描述介面或類中宣告的變數;
  7. 方法表集合:緊接著就是方法表集合,用於描述介面或類中宣告的方法;

3 類載入過程大體分為幾步?

類載入步驟

4 什麼時機會出發類載入?

  1. 建立類的例項:使用new關鍵字例項化物件;
  2. 訪問類的靜態變數:getstatic或putstatic,讀取或設定一個類的靜態變數(不包括被final修飾的靜態變數);
  3. 訪問類的靜態方法:invokestatic呼叫一個類的靜態方法;
  4. 使用java.lang.reflect進行反射呼叫:如,Class.forName("xxxxx");
  5. 子類初始化時,會先初始化父類

5 被動引用有幾種,被動引用不會觸發類初始化?

  1. 通過子類引用父類的靜態欄位,不會導致子類初始化,只會初始化父類;
  2. 通過陣列定義來引用類,不會觸發類的初始化;
  3. 常量在編譯階段會存入呼叫類的常量池中,本質上並沒有直接引用到定義常量的類,因為不會觸發定義常量的類初始化;

6 類載入:第一步載入階段具體過程?

  1. 通過類的全限定名稱獲取定義此類的二進位制流;
  2. 將二進位制流靜態結構轉化為方法區的執行時資料結構;
  3. 在記憶體中生成一個代表這個類的java.lang.Class物件。對於HotSpot虛擬機器,Class物件是存放在方法區裡的;

7 類載入:第二步驗證階段具體過程?

主要作用就是確保Class檔案的位元組流中包含的資訊符合當前虛擬機器的要求,並且不會危害虛擬機器自身安全;

  1. 檔案格式驗證:對檢查格式、版本;
  2. 後設資料驗證:對位元組碼進行語義分析;
  3. 位元組碼驗證
  4. 符號引用驗證

8 類載入:第三步準備階段具體過程?

  1. 正式為類變數分配記憶體,記憶體在方法區中進行分配,類變數是指static修飾的變數;
  2. 設定類變數的初始值,這個初始值通常情況下是資料型別的零值,如:public static int value = 123;初始值是0,不是123,賦值123動作會在初始化階段才會執行;

9 類載入:第四步解析階段具體過程?

將Class檔案的常量池內的符號引用替換為直接引用;

10 類載入:第五步初始化具體過程?

真正開始執行類中定義的Java程式程式碼,初始化過程就是執行類構造器()方法的過程;

  1. ()方法會自動收集類中所有類變數(static)的賦值動作和靜態程式碼塊,編譯器收集順序由程式碼出現順序決定;
  2. ()方法與類例項建構函式不同,虛擬機器會保證父類的()執行完畢後再執行子類的()方法;

12 類載入器有幾種,每種的作用?

類載入器

  1. 根類載入器(Bootstrap ClassLoader):其負責載入Java的核心類,比如String、System這些類;
  2. 擴充類載入器(Extension ClassLoader):其負責載入JRE的擴充類庫;
  3. 系統類載入器(System ClassLoader):其負責載入CLASSPATH環境變數所指定的JAR包和類路徑;
  4. 使用者類載入器:使用者自定義的載入器,以類載入器為父類

13 類載入器雙親委託模式是什麼及為什麼?

雙親委派機制:如果一個類載入器在接到載入類的請求時,它首先不會自己嘗試去載入這個類,而是把這個請求任務委託給父類載入器去完成,依次遞迴,如果父類載入器可以完成類載入任務,就成功返回;只有父類載入器無法完成此載入任務時,才自己去載入。

Java類隨著載入它的類載入器一起具備了一種帶有優先順序的層次關係。比如,Java中的Object類,它存放在rt.jar之中,無論哪一個類載入器要載入這個類,最終都是委派給處於模型最頂端的啟動類載入器進行載入,因此Object在各種類載入環境中都是同一個類。如果不採用雙親委派模型,那麼由各個類載入器自己取載入的話,那麼系統中會存在多種不同的Object類。

相關文章