虛擬機如何加載Class文件?
Class文件裏的信息進入虛擬機會發生怎樣的變化?
虛擬機把描述類的數據從class文件加載到內存,並對數據進行校驗、轉換解析和初始化,最終形成可以被虛擬機直接使用的Java類型,這就是類加載機制
類加載的時機
類從被加載到內存到卸載出內存,生命週期:
加載、連接(驗證、準備、解析)、初始化、使用、卸載
初始化
- 遇到new、getstatic、putstatic或invokestatic,若類未初始化,則觸發初始化
- 使用java.lang.reflect對類進行反射調用
- 父類沒有進行過初始化,先初始化父類
- 虛擬機啓動時,先初始化要執行的主類
- 若java.lang.invoke.MethodHandle實例最後的解析結果爲REF_getStatic、REF_putStatic、REF_invokeStatic的句柄,若此方法句柄對應的類沒有進行過初始化,則要先初始化。
下面以代碼來演示
//父類superClass
public class SuperClass {
static {
System.out.println("SuperClass init!");
}
public static int sup = 1111111;
}
//子類subClass
public class subClass extends SuperClass{
static {
System.out.println("SubClass init!");
}
public static int sub = 2222222;
}
guess結果是啥?
分析,參考上面規則的第三條: 3. 父類沒有進行過初始化,先初始化父類
首先是subClass.sub:要調用子類中的靜態變量sub,那就要初始化子類,但是在子類初始化之前,還要去先初始化父類,最後纔打印sub的值
在運行第二句時,兩個類已經經過初始化,那麼直接打印值即可。
public static void main(String[] args) {
SuperClass[] sca = new SuperClass[10];;
}
這樣,並沒有輸出superClass init!
它代表了元素類型爲superClass的一維數組,它是繼承於java.lang.Object的子類
public class ConstClass {
static{
System.out.println("ConstClass init!");
}
public static final String Hello = "Hello!";
}
public class NotInitialization {
public static void main(String[] args) {
System.out.println(ConstClass.Hello);
}
}
輸出什麼?
Hello!
爲啥沒有執行static裏面的語句呢???
這裏用了final,即Hello是常量,它被存放在常量池中,和ConstClass這個類沒有了聯繫,主函數在執行時,不需要對ConstClass類進行初始化,所以最終只打印“ Hello!”