1. 程式人生 > >《深入了解Java虛擬機》筆記-jvm 類加載機制

《深入了解Java虛擬機》筆記-jvm 類加載機制

類加載機制 ant 常量 extends 場景 int 讀取 修飾 stat

一、類的初始化

主動引用:比較常見的場景有

1、使用new關鍵字去實例化一個對象,讀取或者設置一個類的靜態字段(被final修飾的靜態常量除外,這樣的字段會在編譯階段被放入常量池中,不會觸發類的加載),調用一個類的靜態方法。

2、使用java.lang.reflect的方法對類進行反射調用的時候,如果類沒有被初始化,則會初始化這個類

3、當初始化一個子類的時候,如果其父類還沒有進行初始化,則要先觸發其父類的初始化。

4、虛擬機啟動時會初始化程序的入口類(比如包含main方法的那個類)

以上的四種情形都是對類的主動引用,會觸發類的初始化。

被動引用:

1、子類引用父類的靜態變量,不會觸發子類的初始化。對於一個靜態變量,只有直接定義這個字段的類才會被初始化。

class Parent {
    static {
        System.out.println("parent init!");
    }
    protected static String val = "jvm";
}

class Child extends Parent{
    static {
        System.out.println("child init");
    }
}

public class InitDemo{
    public static void main(String[] args) {
        System.out.println(Child.val);
    }
}
結果為:
parent init!
jvm

子類沒有被初始化

2、常量在編譯階段會被放入到調用類的常量池中,本質上沒有直接引用到定義常量的類,不會觸發定義常量的類的初始化

class Normal{
    public final static String str = "jvm";
    static {
        System.out.println("Normal init");
    }
}

public class ConstantDemo {
    public static void main(String[] args) {
        System.out.println(Normal.str);
    }
}
結果為:
jvm

Normal 類並沒有被初始化

上面的代碼在執行過程中並沒有輸出Normal init,雖然ConstantDemo 在源碼中引用了Normal類的常量str,但是在編譯階段此常量的值"jvm"存儲到了ConstantDemo的常量池中,對常量Normal.str的引用轉化成ConstantDemo對於自身常量池的引用了,因此不會觸發Normal 類的初始化。

《深入了解Java虛擬機》筆記-jvm 類加載機制