什么是雙親委派機(jī)制
當(dāng)某個(gè)類加載器需要加載某個(gè).class
文件時(shí)鱼填,它首先把這個(gè)任務(wù)委托給他的上級(jí)類加載器,遞歸這個(gè)操作,如果上級(jí)的類加載器沒有加載魁袜,自己才會(huì)去加載這個(gè)類。
類加載器的類別
BootstrapClassLoader(啟動(dòng)類加載器)
c++
編寫敦第,加載java
核心庫(kù) java.*
,構(gòu)造ExtClassLoader
和AppClassLoader
峰弹。由于引導(dǎo)類加載器涉及到虛擬機(jī)本地實(shí)現(xiàn)細(xì)節(jié),開發(fā)者無(wú)法直接獲取到啟動(dòng)類加載器的引用申尼,所以不允許直接通過(guò)引用進(jìn)行操作
ExtClassLoader (標(biāo)準(zhǔn)擴(kuò)展類加載器)
java
編寫垮卓,加載擴(kuò)展庫(kù),如classpath
中的jre
师幕,javax.*
或者
java.ext.dir
指定位置中的類粟按,開發(fā)者可以直接使用標(biāo)準(zhǔn)擴(kuò)展類加載器。
AppClassLoader(系統(tǒng)類加載器)
java
編寫霹粥,加載程序所在的目錄灭将,如user.dir
所在的位置的class
CustomClassLoader(用戶自定義類加載器)
java
編寫,用戶自定義的類加載器,可加載指定路徑的class
文件
源碼分析
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
synchronized (getClassLoadingLock(name)) {
// 首先檢查這個(gè)classsh是否已經(jīng)加載過(guò)了
Class<?> c = findLoadedClass(name);
if (c == null) {
long t0 = System.nanoTime();
try {
// c==null表示沒有加載,如果有父類的加載器則讓父類加載器加載
if (parent != null) {
c = parent.loadClass(name, false);
} else {
//如果父類的加載器為空 則說(shuō)明遞歸到bootStrapClassloader了
//bootStrapClassloader比較特殊無(wú)法通過(guò)get獲取
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {}
if (c == null) {
//如果bootstrapClassLoader 仍然沒有加載過(guò)后控,則遞歸回來(lái)庙曙,嘗試自己去加載class
long t1 = System.nanoTime();
c = findClass(name);
sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
sun.misc.PerfCounter.getFindClasses().increment();
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
}
委派機(jī)制的流程圖
雙親委派機(jī)制的作用
1、防止重復(fù)加載同一個(gè).class
浩淘。通過(guò)委托去向上面問一問捌朴,加載過(guò)了,就不用再加載一遍张抄。保證數(shù)據(jù)安全砂蔽。
2、保證核心.class
不能被篡改署惯。通過(guò)委托方式左驾,不會(huì)去篡改核心.clas
,即使篡改也不會(huì)去加載极谊,即使加載也不會(huì)是同一個(gè).class
對(duì)象了诡右。不同的加載器加載同一個(gè).class
也不是同一個(gè)Class
對(duì)象。這樣保證了Class
執(zhí)行安全轻猖。