JVM類加載時機

類加載過程簡述:

Java虛擬機把描述類的內容從class文件中加載到虛擬機內存中,對其校驗、轉換解析、初始化。最終形成可以被虛擬機直接使用的java類型,此過程成爲虛擬機的類加載過程

 

類加載時機

 

類的生命週期:

虛擬機中類的生命週期從被加載到虛擬機內存中開始,卸載出內存爲止。總共包括:加載、驗證、準備、解析、初始化、使用和卸載7個階段。其中驗證、準備、解析三階段被稱爲連接階段。

各階段執行時機:

加載、驗證、準備、初始化、卸載五個階段的執行順序是固定不變的,其中加載、驗證、準備三步必須在初始化之前開始,解析階段可能會在初始化之後開始。這些階段通常都是交叉混合進行的,可能在執行一個階段時會激活、調用其他階段。

主動引用:

Java虛擬機規範中並未規定何時開始執行加載階段,但是有6種情況下必定會觸發初始化階段。

  1. 遇到new、getStatic、putStatic、invokeStatic四個指令時,若該類未初始化則觸發其初始化。以下爲典型場景:
    1. 使用new指令對類實例化時
    2. 調用、設置一個類型的靜態字段時(被final修飾過的或者在編譯階段就將結果存入常量池中的靜態字段除外)
    3. 調用一個類型的靜態方法時
  2. 使用java.lang.reflect包中的方法對類進行反射調用時,若該類未初始化則觸發其初始化
  3. 對類進行初始化時先檢查該類父類是否初始化,若未初始化則觸發其初始化
  4. 虛擬機啓動時,需要用戶指定一個主類,並將其初始化(包括main()的類)
  5. JDK7時,如果一個java.lang.invoke.MethodHandle實例的解析結果爲REF_getStatic、REF_putStatic、REF_invokeStatic、REF_newInvokeSpecial四種方法句柄時,如果該句柄所對應的類未初始化則觸發其初始化
  6. 如果一個接口中的方法被定義爲JDK8中的默認方法(被default所修飾的方法)時,若該接口的實現類即將初始化則需先將該類進行初始化

被動引用:

有且僅有以上6種情況會對類進行主動初始化,除此之外的所有類型都不會被主動初始化

  1. 子類引用父類的靜態字段,不會觸發子類的初始化
  2. 用數組定義的引用類,該引用類不會觸發初始化
  3. 常量在編譯階段時存入調用類的常量池中,並沒有直接引用定義常量的類,不會對定義常量的類觸發初始化

類和接口加載時的區別

上述所說的類描述比較籠統,實際上在接口加載時與類加載時是有所區別的,在有且僅有的6中主動引用中的第三種:在對類進行初始化之前,先對其父類進行初始化,在對接口初始化時,不會強制其所有父接口初始化,只有用到這個父接口時纔會對其初始化

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章