類加載
- 在Java代碼中,類型(class 、interface、 enum etc)的加載(将位元組碼從磁盤加載到記憶體),連接配接(類與類之間的關系的連接配接)與初始化過程都是在程式運作期間完成的,加載,連接配接,初始化順序不是固定的,不同的虛拟機實作不一樣。
- 提供了更大的靈活性,增加了更多的可能性。
類加載器深入剖析
- Java虛拟機與程式的周期
- 在如下幾種情況下,Java虛拟機将結束生命周期。
- 執行了System.ext()方法。
- 程式正常執行結束
- 程式在執行過程中遇到了異常或錯誤而異常終止。
- 由于作業系統錯誤而導緻Java虛拟機程序終止。
- -
類的加載、連接配接與初始化
- 加載:查找并加載類的二進制資料
- 連接配接:
- 驗證:確定被加載類的正确性。
- 準備:為類的靜态變量配置設定記憶體,并将其初始化為預設值。
- 解析:把類中的符号引用裝換為直接引用。
- 初始化:為類的靜态變量賦予正确的初始值。
-
Java程式對類的使用方式可分為2種:
- 主動使用
- 被動使用
- 所有的Java虛拟機實作必須在每個類或者接口被Java程式“首次主動使用”時才初始化他們。
- 主動使用(七種)
- 建立類的執行個體。
- 通路某個類或者接口的靜态變量,或者對該靜态變量指派。
- 調用類的靜态方法。
- 反射 (如Class.forName(“com.test.Test”))
- 初始化一個類的子類
- Jav啊虛拟機啟動時被标明為啟動類的類(Java Test)
-
JDK1.7開始提供的動态 語言支援:
Java.lang.invoke.MethodHandle執行個體的解析結果REF_getStattic REF_putStatic REF_invokeStatic句柄對應的類如果沒有初始化,則初始化(了解)
除了以上七中情況,其他使用Java類的方式都被看做是對類的被動使用,都不會導緻類的初始化(指的是加載,連接配接,初始化這個步驟的初始化)
執行個體介紹:
public class MyTest {
/*
對于靜态字段來說,隻有直接定義該字段的類才會被初始化
當一個類初始化時,要求其父類全部都已經初始化完畢了
-XX:+TraceClassLoading 用于追蹤類的加載資訊并列印出來
-XX:+<option> 表示開啟option選項
-XX:-<option> 表示關閉option選項
-XX:<option>=<value>,表示将option的選項的值設定為value
*/
public static void main(String[] args) {
//直接使用父類的變量 ,子類不會初始化,雖有用了子類的辨別符
System.out.println(MyChild.str);
/*
MyParent1 static block
hello world
*/
//直接調用子類的變量 會首先初始化父類,然後再初始化子類
// System.out.println(MyChild.str2);
/*
MyParent1 static block
MyChild static bloack
welcome
*/
}
}
class MyParent1{
public static String str = "hello world";
static{
System.out.println("MyParent1 static block");
}
}
class MyChild extends MyParent1{
public static String str2 = "welcome";
static{
System.out.println("MyChild static bloack");
}
}
類的加載:
- 類的加載指的是将類的.class檔案中的二進制資料讀入到記憶體中,将其放在運作時資料區的方法區,然後在記憶體中建立一個Java.lang.Class對象(規範并未說明Class對象位于哪裡,HotPot虛拟機将其放在了方法區中)用來封裝類在方法區内的資料結構。
- 加載.class檔案的方式
- 從本地系統中直接加載
- 通過網絡下載下傳.class檔案
- 從zip,jar等歸檔檔案中加載.class檔案
- 從專有資料庫中提取 .class檔案
- 将Java源檔案動态編譯為.class檔案
類的使用與解除安裝
- 使用 :正常的使用,調用類的方法等
- 解除安裝 :從記憶體中解除安裝。