天天看點

bootstraptable treeGrid 懶加載_jvm之java類加載機制和類加載器(ClassLoader)

當程式主動使用某個類時,如果該類還未被加載到記憶體中,則JVM會通過加載、連接配接、初始化3個步驟來對該類進行初始化。如果沒有意外,JVM将會連續完成3個步驟,是以有時也把這個3個步驟統稱為類加載或類初始化。

bootstraptable treeGrid 懶加載_jvm之java類加載機制和類加載器(ClassLoader)

一 類加載機制

1.1 加載

加載主要是将.class檔案(并不一定是.class。可以是ZIP包,網絡中擷取)中的二進制位元組流讀入到JVM中。

在加載階段,JVM需要完成3件事:

1)通過類的全限定名擷取該類的二進制位元組流;

2)将位元組流所代表的靜态存儲結構轉化為方法區的運作時資料結構;

3)在記憶體中生成一個該類的java.lang.Class對象,作為方法區這個類的各種資料的通路入口。

1.2 連接配接

1.2.1 驗證

驗證是連接配接階段的第一步,主要確定加載進來的位元組流符合JVM規範。

驗證階段會完成以下4個階段的檢驗動作:

1)檔案格式驗證

2)中繼資料驗證(是否符合Java語言規範)

3)位元組碼驗證(确定程式語義合法,符合邏輯)

4)符号引用驗證(確定下一步的解析能正常執行)

1.2.2 準備

準備是連接配接階段的第二步,主要為靜态變量在方法區配置設定記憶體,并設定預設初始值。

1.2.3 解析

解析是連接配接階段的第三步,是虛拟機将常量池内的符号引用替換為直接引用的過程。

1.3 初始化

初始化階段是類加載過程的最後一步,主要是根據程式中的指派語句主動為類變量指派。

注:

1)當有父類且父類為初始化的時候,先去初始化父類;

2)再進行子類初始化語句。

什麼時候需要對類進行初始化?1)使用new該類執行個體化對象的時候;

2)讀取或設定類靜态字段的時候(但被final修飾的字段,在編譯器時就被放入常量池的靜态字段除外static final);

3)調用類靜态方法的時候;

4)使用反射Class.forName(“xxxx”)對類進行反射調用的時候,該類需要初始化;

5) 初始化一個類的時候,有父類,先初始化父類(注:1. 接口除外,父接口在調用的時候才會被初始化;2.子類引用父類靜态字段,隻會引發父類初始化);

6) 被标明為啟動類的類(即包含main()方法的類)要初始化;

7)當使用JDK1.7的動态語言支援時,如果一個java.invoke.MethodHandle執行個體最後的解析結果REF_getStatic、REF_putStatic、REF_invokeStatic的方法句柄,并且這個方法句柄所對應的類沒有進行過初始化,則需要先觸發其初始化。

以上情況稱為對一個類進行主動引用,且有且隻要以上幾種情況需要對類進行初始化。

二 類加載器

類加載器實作的功能是即為加載階段擷取二進制位元組流的時候。

JVM提供了以下3種系統的類加載器:

  • **啟動類加載器(Bootstrap ClassLoader):**最頂層的類加載器,負責加載 JAVA_HOME\lib 目錄中的,或通過-Xbootclasspath參數指定路徑中的,且被虛拟機認可(按檔案名識别,如rt.jar)的類。
  • **擴充類加載器(Extension ClassLoader):**負責加載 JAVA_HOME\lib\ext 目錄中的,或通過java.ext.dirs系統變量指定路徑中的類庫。
  • **應用程式類加載器(Application ClassLoader):**也叫做系統類加載器,可以通過getSystemClassLoader()擷取,負責加載使用者路徑(classpath)上的類庫。如果沒有自定義類加載器,一般這個就是預設的類加載器。

類加載器之間的層次關系如下:

bootstraptable treeGrid 懶加載_jvm之java類加載機制和類加載器(ClassLoader)

繼續閱讀