虛擬機器類載入機制_類載入時機和類的生命週期
類載入機制
類的生命週期
類從被載入到虛擬機器記憶體中開始,到解除安裝出記憶體為止,生命週期包括:
載入、驗證、準備、解析、初始化、使用和解除安裝7個階段。其中驗證、準備、解析3個部分統稱為連線。
載入、驗證、準備、初始化和解除安裝這5個階段的順序是確定的,類的載入過程必須按照這種順序按部就班地開始,
可以在初始化之後再解析,為了支援java語言執行時繫結
類的初始化時機
java虛擬機器規範中並沒有對載入有強制約束,但是對於類的初始化,java虛擬機器規範中嚴格規定有且只有5種情況必須進行:
1> 遇到new、getstatic、putstatic或invokestatic這4條位元組碼指令時候,如果類沒有進行初始化,則會觸發初始化,
最常見的場景:使用new 例項化物件的時候、讀取或者設定一個類的靜態欄位(被final修飾、已在編譯期間把結果放入常量池的靜態欄位除外)的時候,以及呼叫類的靜態方法的時候
2> 使用java.lang.reflect包的時候對類進行反射呼叫的時候,如果類沒有進行過初始化,則需要先觸發其初始化
3> 初始化一個類的時候,如果發現父類還沒有進行過初始化,則需要先觸發其父類的初始化
4> 當虛擬機器啟動時候,使用者需要制定一個執行的主類(包含main方法的類),這個類會優先初始化
5> 當使用JDK1.7動態語言支援時,如果一個java.lang.invoke.MethodHandle例項最後解析方法控制程式碼是:
REF_getStatic、REF_putStatic、REF_invokeStatic,並且這個控制程式碼對應的類沒有進行過初始化,需要出發初始化操作
note:
上面的5種場景中的行為成為對一個類進行主動引用,除此之外,所有引用類的方式都不會觸發初始化,稱為被動引用。
被動引用的場景
1 . 子類呼叫父類的靜態變數:只會觸發父類的初始化、不會觸發子類的初始化
class SuperClass{
static{
System.out.println("SuperClass init! ");
}
public static int value = 1;
}
class SubClass extends SuperClass{
static{
System.out.println("SubClass init !");
}
}
public class Test {
public static void main(String[] args) throws ParseException {
System.out.println(SubClass.value);
}
}
輸出結果:
證明子類呼叫父類的靜態變數,不會去觸發子類的初始化
SuperClass init!
1
如果將父類的變數改為常量,子類呼叫這個常量,也不會去觸發父類的初始化
1
2.通過陣列定義來引用類,不會觸發此類的初始化
public static void main(String[] args) throws ParseException {
SuperClass[] test = new SuperClass[10];
}
3. 常量在編譯階段會存入呼叫類的常量池中,本質上並沒有直接引用到定義常量的類,不會觸發類的初始化class ConstClass{
static{
System.out.println("ConstClass init ");
}
public static final String HELLOWORLD = "hello world!";
}
public class Test {
public static void main(String[] args) throws ParseException {
System.out.println(ConstClass.HELLOWORLD);
}
}
結果並不會去輸出"ConstClass Init!",因為原始碼雖然引用了常量資訊,但是在編譯期間已將常量的值hello world儲存到Test類的常量池中,以後對常量的引用都轉為對自身常量池的引用.也就是Test類的class檔案中沒有ConstClass類的符號引用入口,這兩個類在編譯成class之後就不存在任何聯絡
注意:
介面的載入過程和類載入過程有一些不同,針對介面需要做一些特殊說明:介面也有初始化過程,前面測試中使用static{}來輸出初始化資訊的,介面中不能使用static{}語句塊,但是編譯器仍然會為介面生成<clinit>()類構造器,用於初始化介面中定義的成員變數。
介面和類真正有區別的地方是:當一個類在初始化時,要求父類全部都已經初始化過了,但是一個介面在初始化時,並不要求父介面全部完成初始化,只有在真正使用到父介面(如引用介面中定義的變數)才會初始化
相關文章
- 虛擬機器類載入機制:類載入時機虛擬機
- 虛擬機器類載入機制_類載入的過程虛擬機
- 虛擬機器類載入機制虛擬機
- java虛擬機器類載入機制Java虛擬機
- Java 虛擬機器類載入機制Java虛擬機
- Java虛擬機器(六):類載入機制Java虛擬機
- JVM(7)-虛擬機器類載入機制JVM虛擬機
- 虛擬機器系列 | JVM類載入機制虛擬機JVM
- JVM(五)----虛擬機器類載入機制JVM虛擬機
- JVM學習-虛擬機器類載入機制JVM虛擬機
- JVM(三)-java虛擬機器類載入機制JVMJava虛擬機
- 探祕類載入器和類載入機制
- 深入理解虛擬機器之虛擬機器類載入機制虛擬機
- Java 虛擬機器之四:Java類載入機制Java虛擬機
- 深入理解Java虛擬機器 - 類載入機制Java虛擬機
- 深入理解JVM,虛擬機器類載入機制JVM虛擬機
- 深入理解Java虛擬機器(類載入機制)Java虛擬機
- 深入理解Java虛擬機器 --- 類載入機制Java虛擬機
- 【Java虛擬機器規範】JVM類載入機制Java虛擬機JVM
- 深入理解JVM(③)虛擬機器的類載入時機JVM虛擬機
- 深入java虛擬機器學習–類的載入機制(四)Java虛擬機機器學習
- 類載入流程,類載入機制及自定義類載入器
- 類載入機制
- 【JVM進階之路】十四:類載入器和類載入機制JVM
- 是時候瞭解一波虛擬機器的類載入機制虛擬機
- 自定義類載入器驗證類載入機制
- 類的載入機制
- 深入淺出JVM(三)之HotSpot虛擬機器類載入機制JVMHotSpot虛擬機
- 深入理解jvm-2Edition-虛擬機器類載入機制JVM虛擬機
- JVM:類載入機制JVM
- JVM類載入機制JVM
- java類載入機制Java
- 類的載入時機
- jvm虛擬機器載入類,是把類的屬性和方法全載入了嗎JVM虛擬機
- Java基礎-類載入器以及載入機制Java
- 類檔案的結構、JVM 的類載入過程、類載入機制、類載入器、雙親委派模型JVM模型
- 類載入機制總結
- 類載入機制與反射反射