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