日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

java classLoader 體系結(jié)構(gòu)

系統(tǒng) 2516 0

原文出處: http://blog.chenlb.com/2009/06/java-classloader-architecture.html

jvm classLoader architecture:

  1. Bootstrap ClassLoader/啟動類加載器 ?
    主要負責(zé)jdk_home/lib目錄下的核心 api 或 -Xbootclasspath 選項指定的jar包裝入工作。
  2. Extension ClassLoader/擴展類加載器 ?
    主要負責(zé)jdk_home/lib/ext目錄下的jar包或 -Djava.ext.dirs 指定目錄下的jar包裝入工作。
  3. System ClassLoader/系統(tǒng)類加載器 ?
    主要負責(zé)java -classpath/-Djava.class.path所指的目錄下的類與jar包裝入工作。
  4. User Custom ClassLoader/用戶自定義類加載器(java.lang.ClassLoader的子類) ?
    在程序運行期間, 通過java.lang.ClassLoader的子類動態(tài)加載class文件, 體現(xiàn)java動態(tài)實時類裝入特性。

類加載器的特性:

  1. 每個ClassLoader都維護了一份自己的名稱空間, 同一個名稱空間里不能出現(xiàn)兩個同名的類。
  2. 為了實現(xiàn)java安全沙箱模型頂層的類加載器安全機制, java默認采用了 " 雙親委派的加載鏈 " 結(jié)構(gòu)。
classloader-architecture

classloader-architecture

classloader-class-diagram

classloader-class-diagram

類圖中, BootstrapClassLoader是一個單獨的java類, 其實在這里, 不應(yīng)該叫他是一個java類。因為,它已經(jīng)完全不用java實現(xiàn)了。它是在jvm啟動時, 就被構(gòu)造起來的, 負責(zé)java平臺核心庫。

自定義類加載器加載一個類的步驟

classloader-load-class

classloader-load-class

ClassLoader 類加載邏輯分析, 以下邏輯是除 BootstrapClassLoader 外的類加載器加載流程:

  1. //?檢查類是否已被裝載過 ??
  2. Class?c?=?findLoadedClass(name);??
  3. if ?(c?==? null ?)?{??
  4. ????? //?指定類未被裝載過 ??
  5. ????? try ?{??
  6. ????????? if ?(parent?!=? null ?)?{??
  7. ????????????? //?如果父類加載器不為空,?則委派給父類加載 ??
  8. ?????????????c?=?parent.loadClass(name,? false ?);??
  9. ?????????}? else ?{??
  10. ????????????? //?如果父類加載器為空,?則委派給啟動類加載加載 ??
  11. ?????????????c?=?findBootstrapClass0(name);??
  12. ?????????}??
  13. ?????}? catch ?(ClassNotFoundException?e)?{??
  14. ????????? //?啟動類加載器或父類加載器拋出異常后,?當(dāng)前類加載器將其 ??
  15. ????????? //?捕獲,?并通過findClass方法,?由自身加載 ??
  16. ?????????c?=?findClass(name);??
  17. ?????}??
  18. }??

線程上下文類加載器
java默認的線程上下文類加載器是 系統(tǒng)類加載器(AppClassLoader)。

  1. //?Now?create?the?class?loader?to?use?to?launch?the?application ??
  2. try ?{??
  3. ????loader?=?AppClassLoader.getAppClassLoader(extcl);??
  4. }? catch ?(IOException?e)?{??
  5. ???? throw ? new ?InternalError(??
  6. "Could?not?create?application?class?loader" ?);??
  7. }???
  8. ??
  9. //?Also?set?the?context?class?loader?for?the?primordial?thread. ??
  10. Thread.currentThread().setContextClassLoader(loader);??

以上代碼摘自sun.misc.Launch的無參構(gòu)造函數(shù)Launch()。

使用線程上下文類加載器, 可以在執(zhí)行線程中, 拋棄雙親委派加載鏈模式, 使用線程上下文里的類加載器加載類.
典型的例子有, 通過線程上下文來加載第三方庫jndi實現(xiàn), 而不依賴于雙親委派.
大部分java app服務(wù)器(jboss, tomcat..)也是采用contextClassLoader來處理web服務(wù)。
還有一些采用 hotswap 特性的框架, 也使用了線程上下文類加載器, 比如 seasar (full stack framework in japenese).

線程上下文從根本解決了一般應(yīng)用不能違背雙親委派模式的問題.
使java類加載體系顯得更靈活.

隨著多核時代的來臨, 相信多線程開發(fā)將會越來越多地進入程序員的實際編碼過程中. 因此,
在編寫基礎(chǔ)設(shè)施時, 通過使用線程上下文來加載類, 應(yīng)該是一個很好的選擇。

當(dāng)然, 好東西都有利弊. 使用線程上下文加載類, 也要注意, 保證多根需要通信的線程間的類加載器應(yīng)該是同一個,
防止因為不同的類加載器, 導(dǎo)致類型轉(zhuǎn)換異常(ClassCastException)。

為什么要使用這種雙親委托模式呢?

  1. 因為這樣可以避免重復(fù)加載,當(dāng)父親已經(jīng)加載了該類的時候,就沒有必要子ClassLoader再加載一次。
  2. 考慮到安全因素,我們試想一下,如果不使用這種委托模式,那我們就可以隨時使用自定義的String來動態(tài)替代java核心api中定義類型,這樣會存在非常大的安全隱患,而雙親委托的方式,就可以避免這種情況,因為String已經(jīng)在啟動時被加載,所以用戶自定義類是無法加載一個自定義的ClassLoader。

java動態(tài)載入class的兩種方式:

  1. implicit隱式,即利用實例化才載入的特性來動態(tài)載入class
  2. explicit顯式方式,又分兩種方式:
    1. java.lang.Class的forName()方法
    2. java.lang.ClassLoader的loadClass()方法

用Class.forName加載類

Class.forName使用的是被調(diào)用者的類加載器來加載類的。
這種特性, 證明了java類加載器中的名稱空間是唯一的, 不會相互干擾。
即在一般情況下, 保證同一個類中所關(guān)聯(lián)的其他類都是由當(dāng)前類的類加載器所加載的。

  1. public ? static ?Class?forName(String?className)??
  2. ????? throws ?ClassNotFoundException?{??
  3. ????? return ?forName0(className,? true ?,?ClassLoader.getCallerClassLoader());??
  4. }???
  5. ??
  6. /**?Called?after?security?checks?have?been?made.?*/ ??
  7. private ? static ? native ?Class?forName0(String?name,? boolean ?initialize,??
  8. ClassLoader?loader)??
  9. ????? throws ?ClassNotFoundException;??

上面中 ClassLoader.getCallerClassLoader 就是得到調(diào)用當(dāng)前forName方法的類的類加載器

static塊在什么時候執(zhí)行?

  • 當(dāng)調(diào)用forName(String)載入class時執(zhí)行,如果調(diào)用ClassLoader.loadClass并不會執(zhí)行.forName(String,false,ClassLoader)時也不會執(zhí)行.
  • 如果載入Class時沒有執(zhí)行static塊則在第一次實例化時執(zhí)行.比如new ,Class.newInstance()操作
  • static塊僅執(zhí)行一次

各個java類由哪些classLoader加載?

  • java類可以通過實例.getClass.getClassLoader()得知
  • 接口由AppClassLoader(System ClassLoader,可以由ClassLoader.getSystemClassLoader()獲得實例)載入
  • ClassLoader類由bootstrap loader載入

NoClassDefFoundError和ClassNotFoundException

  • NoClassDefFoundError:當(dāng)java源文件已編譯成.class文件,但是ClassLoader在運行期間在其搜尋路徑load某個類時,沒有找到.class文件則報這個錯
  • ClassNotFoundException:試圖通過一個String變量來創(chuàng)建一個Class類時不成功則拋出這個異常

java classLoader 體系結(jié)構(gòu)


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 眉山市| 灵川县| 临武县| 龙川县| 梨树县| 留坝县| 鄂托克旗| 印江| 江达县| 盐源县| 罗源县| 沅陵县| 九龙城区| 梁山县| 基隆市| 抚松县| 高碑店市| 德江县| 闽侯县| 安平县| 平湖市| 公安县| 思南县| 德令哈市| 彰武县| 阜新市| 密云县| 涿州市| 苍山县| 滁州市| 沁阳市| 利川市| 河池市| 恩平市| 连江县| 维西| 商河县| 深泽县| 隆尧县| 安丘市| 襄汾县|