類加載機制:
虛擬機把描述類的數(shù)據(jù)從Class文件加載到內(nèi)存,并隊數(shù)據(jù)進行校驗,轉換解析和初始化,最終形成可以被虛擬機直接使用的Java類型。
類生存過程:類加載-使用-卸載
類加載過程 : 加載-連接-初始化
連接過程: 驗證-準備-解析
過程說明
- 加載
- 通過一個類的全限定名來獲取定義此類的二進制字節(jié)流.
- 將這個字節(jié)流所代表的靜態(tài)存儲結構轉化為方法區(qū)的運行時數(shù)據(jù)結構.
- 在內(nèi)存中生成一個代表這個類的Class對象,作為方法區(qū)這個類的各種數(shù)據(jù)訪問入口.
- 驗證
為了確保Class文件的字節(jié)流中包含的信息符合當前虛擬機的要求,并且不會危害虛擬機自身的安全.
文件格式驗證,元數(shù)據(jù)驗證,字節(jié)碼驗證,符號引用驗證.
- 準備
正式為類變量分配內(nèi)存并設置類變量(static 修飾的) 初始值,這些變量所使用的內(nèi)存都將在方法區(qū)中進行分配.
class Test{
int x ; // 對象實例化的時候會分配
static int y =123; //準備后為0, 初始化后為123
static final int z = 123;//準備后為123
}
-
解析
虛擬機將常量池內(nèi)的符號引用替換為直接引用.
-
初始化
初始化階段是執(zhí)行類構造器<clinit>()方法的過程.
<clinit>()方法由編譯器自動收集類中的所有類變量(static變量)的賦值動作和static語句塊中的語句合并產(chǎn)生.
虛擬機保證子類的<clinit>()執(zhí)行之前父類的已經(jīng)執(zhí)行完畢.
虛擬機會保證一個類的<clinit>()方法在多線程的環(huán)境中被正確的加鎖,同步.
5種觸發(fā)初始化的情況:
- new對象,read/write static field(except final static field), invoke static method,如果發(fā)現(xiàn)這個類沒有被加載過;
- java.lang.reflect反射的未初始化的類
- 初始化一個類,如果他的父類未初始化過
- 虛擬機啟動時那個帶main方法的主類
- 如果解析結果是REF_getStatic,REF_putSTatic,REF_invokeStatic,所對應的類沒有初始化過
類中static初始化:
static字段和static語句塊按照先后順序被<clinit>()收集并執(zhí)行。父類的優(yōu)先于子類執(zhí)行。
public class SubCls extends Parent {
static String sub_y = "sub static field y";
static {
System.out.println("sub static block");
sub_x = "sub static block x";
sub_y = "sub static block y";
// System.out.println(sub_x); can not use the field after the block
}
static String sub_x = "sub static field x";
public static void main(String[] args) {
System.out.println(sub_x); // static field x
System.out.println(sub_y); // y - static block
}
}
class Parent {
static String p_x = "parent static field x";
static {
System.out.println("parent static block");
p_x = "parent static block x";
}
}
parent static block
sub static block
sub static field x
sub static block y
雙親委派模型
工作過程:
如果一個類加載器收到了類加載的請求,它首先不會自己去嘗試加載這個類,而是把這個請求委派給父類加載器去完成。每一個層次的類加載器都是如此。只有當父類加載器反饋自己無法完成這個加載請求時,子加載器才會嘗試自己去加載。
好處:
Java類隨著他的類加載器一起具備了一種帶有優(yōu)先級的層次關系。相反如果沒有使用雙親委派模型,由各個類加載器自行去加載的話,如果用戶編寫了一個稱為java.lang.Object的類,并防在ClassPath中,那系統(tǒng)中將出現(xiàn)多個不同的Object類。
類加載器:
- 啟動類加載器(Bootstrap ClassLoader): C++ ; <JAVA_HOME>\lib
- 擴展類加載器(Extension ClassLoader):JAVA ;<JAVA_HOME>\lib\ext
- 應用程序類加載器(Application ClassLoader): JAVA ; ClassPath
- 自定義類加載器(User ClassLoader)