《深入了解Java虛擬機》筆記-jvm 類加載機制
阿新 • • 發佈:2018-09-27
類加載機制 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 類加載機制