類(lèi)加載子系統(tǒng)的作用:
1、負(fù)責(zé)從文件系統(tǒng)或是網(wǎng)絡(luò)中加載.calss文件,class文件在文件開(kāi)頭有特定的文件標(biāo)識(shí)即16進(jìn)制CA TE BA BE;
2、把加載后的class類(lèi)信息存放于方法區(qū),除了類(lèi)信息之外,方法區(qū)還會(huì)存放運(yùn)行時(shí)常量池信息,可能還包括字符串字面量和數(shù)字常量(這部分常量信息是Class文件中常量池部分的內(nèi)存映射);
3、ClassLoader只負(fù)責(zé)class文件的加載,至于它是否可以運(yùn)行,則由Execution Engine決定;
4、如果調(diào)用構(gòu)造器實(shí)例化對(duì)象,則該對(duì)象存放在堆區(qū);

其中類(lèi)加載器的工作內(nèi)容只有左半部分,不包含調(diào)用構(gòu)造器實(shí)例化。
類(lèi)加載器的功能細(xì)分:
類(lèi)加載子系統(tǒng)的執(zhí)行過(guò)程:

加載:通過(guò)類(lèi)的全限定名來(lái)獲取此類(lèi)的二進(jìn)制字節(jié)流;把這個(gè)類(lèi)的靜態(tài)存儲(chǔ)結(jié)構(gòu)轉(zhuǎn)化為方法區(qū)的運(yùn)行時(shí)數(shù)據(jù);在內(nèi)存中生成java.lang.class對(duì)象作為方法區(qū)的各種數(shù)據(jù)的訪問(wèn)入口。
鏈接:鏈接分為三個(gè)階段分別是驗(yàn)證、準(zhǔn)備、解析;
驗(yàn)證:確保.class文件中包含信息符合當(dāng)前虛擬機(jī)的要求,保證被加載類(lèi)的正確性,主要包括文件格式、源數(shù)據(jù)、字節(jié)碼、符號(hào)引用等。
準(zhǔn)備:為類(lèi)變量分配內(nèi)存并設(shè)置初始值,即零值。其中被final修飾的在編譯時(shí)就會(huì)分配,在這里會(huì)顯示初始化,實(shí)例變量也不會(huì)分配,實(shí)例變量會(huì)隨著對(duì)象一起分配到j(luò)ava堆里。
解析:將運(yùn)行時(shí)常量池內(nèi)的符號(hào)引用轉(zhuǎn)為直接引用的過(guò)程。
初始化:執(zhí)行類(lèi)構(gòu)造器<clinit>()的過(guò)程。
此方法不需要定義,是javac編譯器自動(dòng)收集類(lèi)中所有類(lèi)變量的賦值動(dòng)作和靜態(tài)代碼塊中的語(yǔ)句合并而來(lái)。
下面實(shí)例中我們把類(lèi)變量只是掉之后就沒(méi)有再字節(jié)碼中看到<clinit>()方法,關(guān)于靜態(tài)代碼塊也是一樣的。


構(gòu)造器方法clinit()中指令按語(yǔ)句在源文件中出現(xiàn)的順序執(zhí)行。

虛擬機(jī)必須保證一個(gè)類(lèi)的clinit()方法在多線程下被同步加鎖,即一個(gè)類(lèi)只需被clinit一次,之后該類(lèi)的內(nèi)部信息就被存儲(chǔ)在方法區(qū)。

類(lèi)加載器的分類(lèi):
1、jvm支持兩種類(lèi)型的加載器,分別是引導(dǎo)類(lèi)加載器和 自定義加載器
2、引導(dǎo)類(lèi)加載器是由c/c++實(shí)現(xiàn)的,自定義加載器是由java實(shí)現(xiàn)的。
3、jvm規(guī)范定義自定義加載器是指派生于抽象類(lèi)ClassLoder的類(lèi)加載器。

3、上圖中的加載器劃分為包含關(guān)系而并非繼承關(guān)系
4、按照這樣的加載器的類(lèi)型劃分,在程序中我們最常見(jiàn)的類(lèi)加載器是:引導(dǎo)類(lèi)加載器BootStrapClassLoader、自定義類(lèi)加載器(Extension Class Loader、System Class Loader、User-Defined ClassLoader)
啟動(dòng)類(lèi)加載器
1、這個(gè)類(lèi)加載器使用c/c++實(shí)現(xiàn),嵌套再jvm內(nèi)部
2、它用來(lái)加載Java的核心類(lèi)庫(kù)(JAVA_HOME/jre/lib/rt.jar、resource.jar或sun.boot.class.path路徑下的內(nèi)容),用于提供JVM自身需要的類(lèi)。
3、并不繼承自 java.lang.ClassLoader,沒(méi)有父加載器
擴(kuò)展類(lèi)加載器
1、java語(yǔ)言編寫(xiě),由sun.misc.Launcher$ExtClassLoader實(shí)現(xiàn)
2、從java.ext.dirs系統(tǒng)屬性所指定的目錄中加載類(lèi)庫(kù),或從JDK的安裝目錄的jre/lib/ext 子目錄(擴(kuò)展目錄)下加載類(lèi)庫(kù)。如果用戶創(chuàng)建的JAR 放在此目錄下,也會(huì)自動(dòng)由擴(kuò)展類(lèi)加載器加載;派生于 ClassLoader。
3、父類(lèi)加載器為啟動(dòng)類(lèi)加載器
系統(tǒng)類(lèi)加載器
1、java語(yǔ)言編寫(xiě),由 sun.misc.Lanucher$AppClassLoader 實(shí)現(xiàn)
2、該類(lèi)加載是程序中默認(rèn)的類(lèi)加載器,一般來(lái)說(shuō),Java應(yīng)用的類(lèi)都是由它來(lái)完成加載的,它負(fù)責(zé)加載環(huán)境變量classpath或系統(tǒng)屬性java.class.path 指定路徑下的類(lèi)庫(kù);派生于 ClassLoader
3、父類(lèi)加載器為擴(kuò)展類(lèi)加載器
4、通過(guò) ClassLoader#getSystemClassLoader() 方法可以獲取到該類(lèi)加載器。

用戶自定義類(lèi)加載器
在日常的Java開(kāi)發(fā)中,類(lèi)加載幾乎是由三種加載器配合執(zhí)行的,在必要時(shí)我們還可以自定義類(lèi)加載器,來(lái)定制類(lèi)的加載方式。

為什么要自定義類(lèi)加載器
1.隔離加載類(lèi)
2.修改類(lèi)加載的方式
3.拓展加載源
4.防止源碼泄漏
ClassLoder的常用方法

雙親委派機(jī)制
Java虛擬機(jī)對(duì)class文件采用的是按需加載的方式,也就是說(shuō)當(dāng)需要使用該類(lèi)時(shí)才會(huì)將她的class文件加載到內(nèi)存生成的class對(duì)象。而且加載某個(gè)類(lèi)的class文件時(shí),java虛擬機(jī)采用的是雙親委派模式,即把請(qǐng)求交由父類(lèi)處理,它是一種任務(wù)委派模式
