????????Java虛擬機把描述類的數據從Class文件加載到內存,并對數據進行校驗、轉換解析和初始化,最終形成可以被虛擬機直接使用的Java類型,這個過程被稱作虛擬機的類加載機制。Java天生可以動態擴展的語言特性就是依賴運行期間動態加載和動態鏈接這個特點實現的。
1. 類加載的時機
一個類型從被加載到虛擬機內存中開始,到卸載為止,它的整個生命周期將會經過 加載、驗證、準備、解析、初始化、使用、卸載七個階段。其中 驗證、準備、解析三個部分統稱為 連接
加載、驗證、準備、初始化和卸載這五個步驟是不變的,但是解析卻不一定:它在某些情況下可以在初始化階段之后再開始,這是為了支持Java語言的運行是的綁定特性(動態綁定或者晚期綁定)。解析時間具體由虛擬機自己掌握
《Java虛擬機規范》嚴格規定有且只有六種情況必需對類進行初始化。
-
遇到new、getstatic、 putstatic或invokestatic這 四條字節碼指令時,如果類型沒有進行過初始化,則需要先觸發其初始化階段。能夠生成這四條指令的典型Java代碼場景有:
-
使用new關鍵字實例化對象的時候。
-
讀取或設置一個類型的靜態字段(被fnal修飾、已在編譯期把結果放入常量池的靜態字段除外)的時候。
-
調用一個類型的靜態方法的時候。
-
-
使用java. langeflect包的方法對類型進行反射調用的時候,如果類型沒有進行過初始化,則需要先觸發其初始化。
-
當初始化類的時候,如果發現其父類還沒有進行過初始化,則需要先觸發其父類的初始化。
-
當虛擬機啟動時,用戶需要指定一個要執行的主類( 包含main)方法的那個類),虛擬機會先初始化這個主類。
-
當使用JDK 7新加入的動態語言支持時,如果- - -個java. lang invoke. MethodHandle實例最后的解析結果為REF_ getStatic、 REF_ putStatic、 REF_ invokeStatic、 REF newInvokeSpecial四種 類型的方法句柄,并且這個方法句柄對應的類沒有進行過初始化,則需要先觸發其初始化。
-
當一個接口中定義了JDK 8新加入的默認方法(被default關鍵字修飾的接口方法)時,如果有這個接口的實現類發生了初始化,那該接口要在其之前被初始化。
簡化:1.使用new關鍵字,調用類中的靜態屬性,調用類中到的靜態方法 2.反射調用一個類 3.子類進行初始化 4.類為啟動類 5.類的初始化導致實現的接口初始化 6.動態語言