類加載過程簡述:
Java虛擬機把描述類的內容從class文件中加載到虛擬機內存中,對其校驗、轉換解析、初始化。最終形成可以被虛擬機直接使用的java類型,此過程成爲虛擬機的類加載過程
類加載時機
類的生命週期:
虛擬機中類的生命週期從被加載到虛擬機內存中開始,卸載出內存爲止。總共包括:加載、驗證、準備、解析、初始化、使用和卸載7個階段。其中驗證、準備、解析三階段被稱爲連接階段。
各階段執行時機:
加載、驗證、準備、初始化、卸載五個階段的執行順序是固定不變的,其中加載、驗證、準備三步必須在初始化之前開始,解析階段可能會在初始化之後開始。這些階段通常都是交叉混合進行的,可能在執行一個階段時會激活、調用其他階段。
主動引用:
Java虛擬機規範中並未規定何時開始執行加載階段,但是有6種情況下必定會觸發初始化階段。
- 遇到new、getStatic、putStatic、invokeStatic四個指令時,若該類未初始化則觸發其初始化。以下爲典型場景:
- 使用new指令對類實例化時
- 調用、設置一個類型的靜態字段時(被final修飾過的或者在編譯階段就將結果存入常量池中的靜態字段除外)
- 調用一個類型的靜態方法時
- 使用java.lang.reflect包中的方法對類進行反射調用時,若該類未初始化則觸發其初始化
- 對類進行初始化時先檢查該類父類是否初始化,若未初始化則觸發其初始化
- 虛擬機啓動時,需要用戶指定一個主類,並將其初始化(包括main()的類)
- JDK7時,如果一個java.lang.invoke.MethodHandle實例的解析結果爲REF_getStatic、REF_putStatic、REF_invokeStatic、REF_newInvokeSpecial四種方法句柄時,如果該句柄所對應的類未初始化則觸發其初始化
- 如果一個接口中的方法被定義爲JDK8中的默認方法(被default所修飾的方法)時,若該接口的實現類即將初始化則需先將該類進行初始化
被動引用:
有且僅有以上6種情況會對類進行主動初始化,除此之外的所有類型都不會被主動初始化
- 子類引用父類的靜態字段,不會觸發子類的初始化
- 用數組定義的引用類,該引用類不會觸發初始化
- 常量在編譯階段時存入調用類的常量池中,並沒有直接引用定義常量的類,不會對定義常量的類觸發初始化
類和接口加載時的區別
上述所說的類描述比較籠統,實際上在接口加載時與類加載時是有所區別的,在有且僅有的6中主動引用中的第三種:在對類進行初始化之前,先對其父類進行初始化,在對接口初始化時,不會強制其所有父接口初始化,只有用到這個父接口時纔會對其初始化