歡迎光臨郝學(xué)武的blog。

          classloader機(jī)制

          Posted on 2010-04-12 16:35 陜西BOY 閱讀(201) 評(píng)論(0)  編輯  收藏

          當(dāng)JVM(Java虛擬機(jī))啟動(dòng)時(shí),會(huì)形成由三個(gè)類加載器組成的初始類加載器層次結(jié)構(gòu):



                 bootstrap classloader

                 extension classloader

                 system classloader



          bootstrap classloader -引導(dǎo)(也稱為原始)類加載器,它負(fù)責(zé)加載Java的核心類。在Sun的JVM中,在執(zhí)行java的命令中使用-Xbootclasspath選項(xiàng)或使用 - D選項(xiàng)指定sun.boot.class.path系統(tǒng)屬性值可以指定附加的類。這個(gè)加載器的是非常特殊的,它實(shí)際上不是 java.lang.ClassLoader的子類,而是由JVM自身實(shí)現(xiàn)的。大家可以通過(guò)執(zhí)行以下代碼來(lái)獲得bootstrap classloader加載了那些核心類庫(kù):

             URL[] urls=sun.misc.Launcher.getBootstrapClassPath().getURLs();

             for (int i = 0; i < urls.length; i++) {

               System.out.println(urls.toExternalform());

             }

          在我的計(jì)算機(jī)上的結(jié)果為:

          文件:/C:/j2sdk1.4.1_01/jre/lib/endorsed/dom.jar

          文件:/C:/j2sdk1.4.1_01/jre/lib/endorsed/sax.jar

          文件:/C:/j2sdk1.4.1_01/jre/lib/endorsed/xalan-2.3.1.jar

          文件:/C:/j2sdk1.4.1_01/jre/lib/endorsed/xercesImpl-2.0.0.jar

          文件:/C:/j2sdk1.4.1_01/jre/lib/endorsed/xml-apis.jar

          文件:/C:/j2sdk1.4.1_01/jre/lib/endorsed/xsltc.jar

          文件:/C:/j2sdk1.4.1_01/jre/lib/rt.jar

          文件:/C:/j2sdk1.4.1_01/jre/lib/i18n.jar

          文件:/C:/j2sdk1.4.1_01/jre/lib/sunrsasign.jar

          文件:/C:/j2sdk1.4.1_01/jre/lib/jsse.jar

          文件:/C:/j2sdk1.4.1_01/jre/lib/jce.jar

          文件:/C:/j2sdk1.4.1_01/jre/lib/charsets.jar

          文件:/C:/j2sdk1.4.1_01/jre/classes

          這時(shí)大家知道了為什么我們不需要在系統(tǒng)屬性CLASSPATH中指定這些類庫(kù)了吧,因?yàn)镴VM在啟動(dòng)的時(shí)候就自動(dòng)加載它們了。



          extension classloader -擴(kuò)展類加載器,它負(fù)責(zé)加載JRE的擴(kuò)展目錄(JAVA_HOME/jre/lib/ext或者由java.ext.dirs系統(tǒng)屬性指定的)中JAR的類包。這為引入除Java核心類以外的新功能提供了一個(gè)標(biāo)準(zhǔn)機(jī)制。因?yàn)槟J(rèn)的擴(kuò)展目錄對(duì)所有從同一個(gè)JRE中啟動(dòng)的JVM都是通用的,所以放入這個(gè)目錄的 JAR類包對(duì)所有的JVM和system classloader都是可見的。在這個(gè)實(shí)例上調(diào)用方法getParent()總是返回空值null,因?yàn)橐龑?dǎo)加載器bootstrap classloader不是一個(gè)真正的ClassLoader實(shí)例。所以當(dāng)大家執(zhí)行以下代碼時(shí):

             System.out.println(System.getProperty("java.ext.dirs"));

             ClassLoader extensionClassloader=ClassLoader.getSystemClassLoader().getParent();

             System.out.println("the parent of extension classloader : "+extensionClassloader.getParent());

          結(jié)果為:

          C:\j2sdk1.4.1_01\jre\lib\ext

          the parent of extension classloader : null

          extension classloader是system classloader的parent,而bootstrap classloader是extension classloader的parent,但它不是一個(gè)實(shí)際的classloader,所以為null。



          system classloader -系統(tǒng)(也稱為應(yīng)用)類加載器,它負(fù)責(zé)在JVM被啟動(dòng)時(shí),加載來(lái)自在命令java中的-classpath或者java.class.path系統(tǒng)屬性或者 CLASSPATH*作系統(tǒng)屬性所指定的JAR類包和類路徑。總能通過(guò)靜態(tài)方法ClassLoader.getSystemClassLoader()找到該類加載器。如果沒有特別指定,則用戶自定義的任何類加載器都將該類加載器作為它的父加載器。執(zhí)行以下代碼即可獲得:

             System.out.println(System.getProperty("java.class.path"));

          輸出結(jié)果則為用戶在系統(tǒng)屬性里面設(shè)置的CLASSPATH。

          classloader 加載類用的是全盤負(fù)責(zé)委托機(jī)制。所謂全盤負(fù)責(zé),即是當(dāng)一個(gè)classloader加載一個(gè)Class的時(shí)候,這個(gè)Class所依賴的和引用的所有 Class也由這個(gè)classloader負(fù)責(zé)載入,除非是顯式的使用另外一個(gè)classloader載入;委托機(jī)制則是先讓parent(父)類加載器 (而不是super,它與parent classloader類不是繼承關(guān)系)尋找,只有在parent找不到的時(shí)候才從自己的類路徑中去尋找。此外類加載還采用了cache機(jī)制,也就是如果 cache中保存了這個(gè)Class就直接返回它,如果沒有才從文件中讀取和轉(zhuǎn)換成Class,并存入cache,這就是為什么我們修改了Class但是必須重新啟動(dòng)JVM才能生效的原因。





          每個(gè)ClassLoader加載Class的過(guò)程是:

          1.檢測(cè)此Class是否載入過(guò)(即在cache中是否有此Class),如果有到8,如果沒有到2

          2.如果parent classloader不存在(沒有parent,那parent一定是bootstrap classloader了),到4

          3.請(qǐng)求parent classloader載入,如果成功到8,不成功到5

          4.請(qǐng)求jvm從bootstrap classloader中載入,如果成功到8

          5.尋找Class文件(從與此classloader相關(guān)的類路徑中尋找)。如果找不到則到7.

          6.從文件中載入Class,到8.

          7.拋出ClassNotFoundException.

          8.返回Class.



          其中5.6步我們可以通過(guò)覆蓋ClassLoader的findClass方法來(lái)實(shí)現(xiàn)自己的載入策略。甚至覆蓋loadClass方法來(lái)實(shí)現(xiàn)自己的載入過(guò)程。



          類加載器的順序是:

          先是bootstrap classloader,然后是extension classloader,最后才是system classloader。大家會(huì)發(fā)現(xiàn)加載的Class越是重要的越在靠前面。這樣做的原因是出于安全性的考慮,試想如果system classloader“親自”加載了一個(gè)具有破壞性的“java.lang.System”類的后果吧。這種委托機(jī)制保證了用戶即使具有一個(gè)這樣的類,也把它加入到了類路徑中,但是它永遠(yuǎn)不會(huì)被載入,因?yàn)檫@個(gè)類總是由bootstrap classloader來(lái)加載的


          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           

          posts - 17, comments - 65, trackbacks - 0, articles - 28

          Copyright © 陜西BOY

          主站蜘蛛池模板: 夹江县| 九台市| 六盘水市| 定陶县| 新干县| 故城县| 乐安县| 霍林郭勒市| 盈江县| 太仆寺旗| 西和县| 治多县| 高陵县| 绥滨县| 嵊泗县| 宜阳县| 常山县| 阿拉善左旗| 宁都县| 河曲县| 栾川县| 庆安县| 武威市| 封丘县| 红桥区| 陆良县| 六盘水市| 长岛县| 海林市| 安仁县| 伊宁市| 西乌珠穆沁旗| 大丰市| 安多县| 浦城县| 蓬莱市| 高雄市| 长海县| 肇州县| 文安县| 龙州县|