歡迎光臨郝學武的blog。

          classloader機制

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

          當JVM(Java虛擬機)啟動時,會形成由三個類加載器組成的初始類加載器層次結構:



                 bootstrap classloader

                 extension classloader

                 system classloader



          bootstrap classloader -引導(也稱為原始)類加載器,它負責加載Java的核心類。在Sun的JVM中,在執行java的命令中使用-Xbootclasspath選項或使用 - D選項指定sun.boot.class.path系統屬性值可以指定附加的類。這個加載器的是非常特殊的,它實際上不是 java.lang.ClassLoader的子類,而是由JVM自身實現的。大家可以通過執行以下代碼來獲得bootstrap classloader加載了那些核心類庫:

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

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

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

             }

          在我的計算機上的結果為:

          文件:/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

          這時大家知道了為什么我們不需要在系統屬性CLASSPATH中指定這些類庫了吧,因為JVM在啟動的時候就自動加載它們了。



          extension classloader -擴展類加載器,它負責加載JRE的擴展目錄(JAVA_HOME/jre/lib/ext或者由java.ext.dirs系統屬性指定的)中JAR的類包。這為引入除Java核心類以外的新功能提供了一個標準機制。因為默認的擴展目錄對所有從同一個JRE中啟動的JVM都是通用的,所以放入這個目錄的 JAR類包對所有的JVM和system classloader都是可見的。在這個實例上調用方法getParent()總是返回空值null,因為引導加載器bootstrap classloader不是一個真正的ClassLoader實例。所以當大家執行以下代碼時:

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

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

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

          結果為:

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

          the parent of extension classloader : null

          extension classloader是system classloader的parent,而bootstrap classloader是extension classloader的parent,但它不是一個實際的classloader,所以為null。



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

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

          輸出結果則為用戶在系統屬性里面設置的CLASSPATH。

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





          每個ClassLoader加載Class的過程是:

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

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

          3.請求parent classloader載入,如果成功到8,不成功到5

          4.請求jvm從bootstrap classloader中載入,如果成功到8

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

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

          7.拋出ClassNotFoundException.

          8.返回Class.



          其中5.6步我們可以通過覆蓋ClassLoader的findClass方法來實現自己的載入策略。甚至覆蓋loadClass方法來實現自己的載入過程。



          類加載器的順序是:

          先是bootstrap classloader,然后是extension classloader,最后才是system classloader。大家會發現加載的Class越是重要的越在靠前面。這樣做的原因是出于安全性的考慮,試想如果system classloader“親自”加載了一個具有破壞性的“java.lang.System”類的后果吧。這種委托機制保證了用戶即使具有一個這樣的類,也把它加入到了類路徑中,但是它永遠不會被載入,因為這個類總是由bootstrap classloader來加載的


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           

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

          Copyright © 陜西BOY

          主站蜘蛛池模板: 明水县| 东城区| 盐亭县| 都安| 彭水| 温州市| 靖边县| 高阳县| 宁城县| 西峡县| 清新县| 长宁县| 凤庆县| 方城县| 远安县| 扶余县| 阜城县| 湟中县| 兴业县| 嘉定区| 阿拉尔市| 龙里县| 依安县| 山西省| 烟台市| 遵化市| 霞浦县| 永平县| 翁牛特旗| 凌云县| 柯坪县| 木兰县| 东阿县| 凯里市| 米脂县| 咸阳市| 万源市| 罗田县| 青岛市| 虎林市| 巴林右旗|