一、java虛拟機和java程式的生命周期
java虛拟機的生命周期和java程式的生命周期一緻,當我們在指令行中敲入java指令運作java程式時,java虛拟機程序啟動,程式運作,當程式終止時,則java虛拟機的生命也結束。
二、類的生命周期
1、加載:将.class檔案的二進制資料放到記憶體方法區中,并在堆區中建立一個class對象,這個class對象封裝了方法區的資料結構,使用者能通過class對象通路到方法區中。
2、連接配接
(1)驗證:驗證.class檔案是否是通過java程式編譯出來的,因為有可能這個.class檔案是黑客特意制造出來的。
(2)準備:為類中的靜态變量配置設定空間,并初始化為預設值。
(3)解析:把類的符号引用變為直接引用。
3.初始化:為靜态變量和靜态塊賦予值。
java程式對于類的使用方式:
(1)主動使用。
(2)被動使用。
這裡注意:
java虛拟機對于加載和連接配接的時間節點是很寬松的,沒有嚴格規定,可以提前加載也可以;但是對于初始化,java虛拟機規定當某個類被主動使用時才能初始化。
我們把3個步驟細講一下:
1、類的加載:類是通過類加載器進行加載。
類加載的來源:
(1)檔案系統中的class檔案
(2)jar包
(3)網絡中下載下傳。
類加載目的地:記憶體。
類加載器分類:
(1)根類加載器:沒有父類,加載java.lang.*。
(2)擴充類加載器:父類是根類加載器,用于加載jrelibext的jar包。
(3)系統類加載器:父類是擴充類加載器,用于加載classpath的jar包。class scl = class.getsystemclassloader();
(4)自定義加載器:自定義加載,通常父類是系統類加載器。
注意:通過類虛拟機自帶的(1)(2)(3)加載器是java虛拟機建立的,而他們加載的類,他的生命周期是虛拟機的生命周期,因為始終被加載器鎖引用。
2、類的解析
将符号引用轉換成直接引用。比如:
a函數調用了b函數,原本隻是符号引用即标明引用了b函數,直接引用是将符号改成指針指向b函數。
3、類的初始化
規則:
(1)初始化的靜态變量都是運作時變量,即不能在編譯時就能判斷值是多少。
(2)初始化的順序就是按照代碼的順序執行。
(3)如果初始化子類時父類還沒有被初始化,則先初始化父類。
初始化時機:當遇到以下情況會進行初始化。
(1)new建立執行個體、反射建立執行個體、clone建立執行個體、反序列化建立執行個體。
(2)通路靜态變量,即讀和寫。
(3)調用靜态方法。
(4)啟動類需要首先初始化。
(5)class.forname();
注意:
(1)當遇到編譯時常量,則直接用數字替換,而不會導緻類初始化。比如public static final int a= 3;這就是一個編譯時常量。
(2)當子類對象調用父類的靜态變量或方法,則隻對父類進行初始化。比如:sub.a,其中a是父類的靜态變量,則隻對base初始化。
(3)當子類被初始化時,父類一定要先初始化;
但是如果一個類實作了一個接口,當類被初始化時,不用初始化父接口。
隻有對這個接口進行通路時,才會對接口進行初始化。
(4)loader.loadclass("....");隻是對類的加載,而不是初始化。
類加載過程采用“父親委托機制”,即如果loader2的父類是loader1,loader2想要加載test類,則先會檢查loader1是否能夠加載test類,如果能,則通過父類加載。
運作時包的概念:包名相同,類加載器相同。