參考:http://blog.csdn.net/zhuojiajin/article/details/38962087
http://blog.csdn.net/xyang81/article/details/7292380
大家都知道梭冠,當(dāng)我們寫好一個Java程序之后扇救,不是管是CS還是BS應(yīng)用淳地,都是由若干個.class文件組織而成的一個完整的Java應(yīng)用程序荷愕,當(dāng)程序在運行時,即會調(diào)用該程序的一個入口函數(shù)來調(diào)用系統(tǒng)的相關(guān)功能牍帚,而這些功能都被封裝在不同的class文件當(dāng)中儡遮,所以經(jīng)常要從這個class文件中要調(diào)用另外一個class文件中的方法,如果另外一個文件不存在的暗赶,則會引發(fā)系統(tǒng)異常鄙币。而程序在啟動的時候,并不會一次性加載程序所要用的所有class文件蹂随,而是根據(jù)程序的需要十嘿,通過Java的類加載機制(ClassLoader)來動態(tài)加載某個class文件到內(nèi)存當(dāng)中的,從而只有class文件被載入到了內(nèi)存之后岳锁,才能被其它class所引用绩衷。所以ClassLoader就是用來動態(tài)加載class文件到內(nèi)存當(dāng)中用的。
ClassLoader是負(fù)責(zé)加載類的對象激率,作用是根據(jù)Jvm請求提供的類信息咳燕,將請求的類加載的內(nèi)存中或者說加載到Jvm中。另外乒躺,每一個類的Class對象(注意Class是類類型)都持有一個對應(yīng)的ClassLoader的引用招盲。可以通過Class對象的getClassLoader()方法得到嘉冒。類和它的ClassLoader是對應(yīng)的宪肖,所以類只能通過它對應(yīng)的ClassLoader加載。
Java的Classloader有四種分別為:
**bootstrap classloader **:引導(dǎo)(也稱為原始)類加載器健爬。
extension classloader :擴展類加載器。
Application ClassLoader:應(yīng)用程序類加載器么介。
User Defined ClassLoader:自定義類加載器娜遵。
Bootstrap ClassLoader:是用C++編寫的,是JVM的內(nèi)置加載器壤短,它的名字是null设拟。它用來加載核心類庫慨仿,即在lib下的類庫。做個實驗纳胧,首先镰吆,String類肯定是java的核心類,那我們就以它為例來看看:
public static void main(String[] args)
{
String a="x";
System.out.println(a.getClass().getClassLoader());
}
輸出結(jié)果為null跑慕。我們通過代碼獲得了加載String類的ClassLoader的名字万皿,也就是null。
Extension ClassLoader:加載lib/ext下的類庫核行。
App ClassLoader:加載Classpath里的類庫牢硅。
層次關(guān)系
每一個Class對象都會持有一個對應(yīng)的ClassLoader對象的引用。每一個ClassLoader對象也會持有一個Parent ClassLoader對象的引用芝雪。這里需要特別注意的是:這里所指的的Parent ClassLoader不是我們熟悉的繼承關(guān)系减余,不是父類!
舉個例子:
public static void main(String[] args)
{
ClassLoader c = TestClassLoader.class.getClassLoader();
do {
System.out.println(c.getClass().getName());
c=c.getParent();
}while(c!=null);
}
}
輸出為:
sun.misc.Launcher$AppClassLoader
sun.misc.Launcher$ExtClassLoader
這里簡單解釋下上面的代碼惩系,首先獲取TestClassLoader這個類的類類型位岔,通過類類型獲得該類的ClassLoade的對象的引用,將其賦值給c這個新定義的引用變量堡牡。通過這個ClassLoader對象的引用獲得其Parent ClassLoader的對象的引用抒抬。
雙親加載機制
層次關(guān)系中我們了解到了很重要的一點:加載器對象之間的引用關(guān)系。被引用的對象稱之為引用對象的父加載器悴侵,可以通過getParent()方法得到瞧剖。那么雙親加載機制就是基于這種引用的層次關(guān)系。即:當(dāng)一個ClassLoader接到請求時可免,它不是直接加載對應(yīng)的類抓于,而是詢問它引用的ClassLoader是否能夠加載,而這個父ClassLoader則會詢問自己的引用的ClassLoader是否加載了該類浇借。只有當(dāng)所有的父ClassLoader都沒有加載該類時捉撮,這個最初的ClassLoader才自己去加載申請的類。
雙親加載機制可以一定程度上保證安全性妇垢,因為只要頂層ClassLoader能加載的東西就一定不會讓下層的ClassLoader有機會加載巾遭。也就保證了有些自定義的帶有破壞性的類不會被加載到Jvm核心中。
我們試想一下闯估,如果不使用這種委托模式灼舍,那我們就可以隨時使用自定義的String來動態(tài)替代java核心api中定義的類型,這樣會存在非常大的安全隱患涨薪,而雙親委托的方式骑素,就可以避免這種情況,因為String已經(jīng)在啟動時就被引導(dǎo)類加載器(Bootstrcp ClassLoader)加載刚夺,所以用戶自定義的ClassLoader永遠(yuǎn)也無法加載一個自己寫的String献丑,除非你改變JDK中ClassLoader搜索類的默認(rèn)算法末捣。