Java虛擬機加載類的過程

  Java虛擬機的類加載,從class文件到內存中的類,按前後順序須要通過加載/連接/初始化三大步驟.數組

  Java語言的類型分爲兩大類:基本類型(primitive types)和引用類型(reference types).數據結構

  Java的基本類型,是由Java虛擬機預先定義好的.spa

  Java的引用類型,細分爲:類/接口/數組類/泛型參數. 注:泛型參數會在編譯過程當中被擦除,JVM實際上只有前三種.接口

  加載

  加載,是指查找字節流,而且據此建立類的過程. 注:數組類沒有對應的字節流,而是由JVM直接生成的,而其它類則須要藉助類加載器來完成查找字節流的過程.內存

  雙親委派模型:每當一個類加載器接收到加載請求時,它會將請求轉發給父類加載器.在父類加載器沒有找到所請求的類的狀況下,該類加載器纔會嘗試去加載.字符串

  連接

  連接,是指將建立成的類合併至Java虛擬機中,使之可以執行的過程. 分爲驗證/準備/解析三個階段.編譯器

  驗證階段:確保被加載類可以知足Java虛擬機的約束條件.虛擬機

  準備階段:爲被加載類的靜態字段分配內存. 注:部分Java虛擬機還會在此階段構造其它跟類層次相關的數據結構.it

  解析階段:將加載過程當中對類/字段/方法聲明惟一性的符號引用解析成爲實際引用.若是符號引用指向一個未被加載的類,或者未被加載的字段或方法,那麼解析將觸發這個類的加載.編譯

  注:Java虛擬機並無要求在連接過程當中完成解析.規定以下:若是某些字節碼使用了符號引用,則在執行這些字節碼前,須要完成對這些符號引用的解析.

  初始化

  pre:

    若是要初始化一個靜態字段,可在聲明時直接賦值,亦可在靜態代碼塊中對其賦值.

    若是直接賦值的靜態字段被final修飾,且類型爲基本類型或字符串時,則該字段被Java編譯器標記爲常量值(Constant Value),初始化直接由Java虛擬機完成.除此以外的直接賦值操做,以及全部靜態代碼塊中的代碼,則會被Java編譯器置於同一方法中,並命名爲<clinit>

  初始化,爲標記爲常量值的字段賦值,以及執行<clinit>方法的過程. 注:Java虛擬機會經過加鎖來確保類的<clinit>方法僅被執行一次.

  只有當初始化完成以後,類才正式成爲可執行的狀態.

  類初始化的觸發時機枚舉:

    1.當虛擬機啓動時,初始化用戶指定的主類;

    2.當遇到用以新建目標類實例的new指令時,初始化new指令的目標類;

    3.當遇到調用靜態方法的指令時,初始化該靜態方法所在的類;

    4.當遇到訪問靜態字段的指令時,初始化該靜態字段所在的類;

    5.子類的初始化會觸發父類的初始化;

    6.若是一個接口定義了default方法,那麼直接實現或者間接實現該接口的類的初始化,會觸發該接口的初始化;

    7.使用反射API對某個類進行反射調用時,初始化這個類;

    8.當初次調用MethodHandle實例時,初始化該MethodHandle指向的方法所在的類.

相關文章
相關標籤/搜索