java類載入器體繫結構

來源:互聯網
上載者:User

jvm classLoader architecture :

a, Bootstrap ClassLoader/啟動類載入器
主要負責jdk_home/lib目錄下的核心 api 或 -Xbootclasspath 選項指定的jar封裝入工作.

b, Extension ClassLoader/擴充類載入器
主要負責jdk_home/lib/ext目錄下的jar包或 -Djava.ext.dirs 指定目錄下的jar封裝入工作

c, System ClassLoader/系統類別載入器
主要負責java -classpath/-Djava.class.path所指的目錄下的類與jar封裝入工作.

b, User Custom ClassLoader/使用者自訂類載入器(java.lang.ClassLoader的子類)
在程式運行期間, 通過java.lang.ClassLoader的子類動態載入class檔案, 體現java動態即時類裝入特性.

類載入器的特性:

1, 每個ClassLoader都維護了一份自己的名稱空間, 同一個名稱空間裡不能出現兩個同名的類。
2, 為了實現java安全沙箱模型頂層的類載入器安全機制, java預設採用了 ” 雙親委派的載入鏈 ” 結構.
如:

類圖中, BootstrapClassLoader是一個單獨的java類, 其實在這裡, 不應該叫他是一個java類。
因為, 它已經完全不用java實現了。

它是在jvm啟動時, 就被構造起來的, 負責java平台核心庫。(具體上面已經有介紹)

啟動類載入實現 (其實我們不用關心這塊, 但是有興趣的, 可以研究一下 ):
bootstrap classLoader 類載入原理探索

自訂類載入器載入一個類的步驟 :

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

// 檢查類是否已被裝載過Class c = findLoadedClass(name);if (c == null ) {     // 指定類未被裝載過     try {         if (parent != null ) {             // 如果父類載入器不為空白, 則委派給父類載入             c = parent.loadClass(name, false );         } else {             // 如果父類載入器為空白, 則委派給啟動類載入載入             c = findBootstrapClass0(name);         }     } catch (ClassNotFoundException e) {         // 啟動類載入器或父類載入器拋出異常後, 當前類載入器將其         // 捕獲, 並通過findClass方法, 由自身載入         c = findClass(name);     }}

用Class.forName載入類
Class.forName使用的是被調用者的類載入器來載入類的.
這種特性, 證明了java類載入器中的名稱空間是唯一的, 不會相互幹擾.
即在一般情況下, 保證同一個類中所關聯的其他類都是由當前類的類載入器所載入的.

public static Class forName(String className)     throws ClassNotFoundException {     return forName0(className, true , ClassLoader.getCallerClassLoader());} /** Called after security checks have been made. */private static native Class forName0(String name, boolean initialize,ClassLoader loader)     throws ClassNotFoundException;

中 ClassLoader.getCallerClassLoader 就是得到調用當前forName方法的類的類載入器

線程上下文類載入器
java預設的線程上下文類載入器是 系統類別載入器(AppClassLoader).

// Now create the class loader to use to launch the applicationtry {    loader = AppClassLoader.getAppClassLoader(extcl);} catch (IOException e) {    throw new InternalError("Could not create application class loader" );} // Also set the context class loader for the primordial thread.Thread.currentThread().setContextClassLoader(loader);

以上代碼摘自sun.misc.Launch的無參建構函式Launch()。
使用線程上下文類載入器, 可以在執行線程中, 拋棄雙親委派載入鏈模式, 使用線程上下文裡的類載入器載入類.
典型的例子有, 通過線程上下文來載入第三方庫jndi實現, 而不依賴於雙親委派.
大部分java app伺服器(jboss, tomcat..)也是採用contextClassLoader來處理web服務。
還有一些採用 hotswap 特性的架構, 也使用了線程上下文類載入器, 比如 seasar (full stack framework in japenese).

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

隨著多核時代的來臨, 相信多線程開發將會越來越多地進入程式員的實際編碼過程中. 因此,
在編寫基礎設施時, 通過使用線程上下文來載入類, 應該是一個很好的選擇.

當然, 好東西都有利弊. 使用線程上下文載入類, 也要注意, 保證多根需要通訊的線程間的類載入器應該是同一個,
防止因為不同的類載入器, 導致類型轉換異常(ClassCastException).

自訂的類載入器實現
defineClass(String name, byte[] b, int off, int len,ProtectionDomain protectionDomain)
是java.lang.Classloader提供給開發人員, 用來自訂載入class的介面.

使用該介面, 可以動態載入class檔案.

例如,
在jdk中, URLClassLoader是配合findClass方法來使用defineClass, 可以從網路或硬碟上載入class.

而使用類載入介面, 並加上自己的實現邏輯, 還可以定製出更多的進階特性.

比如,

一個簡單的hot swap 類載入器實現:

import java.io.File;import java.io.FileInputStream;import java.lang.reflect.Method;import java.net.URL;import java.net.URLClassLoader; /*** 可以重新載入同名類的類載入器實現* * 放棄了雙親委派的載入鏈模式.* 需要外部維護重載後的類的成員變數狀態.** @author ken.wu* @mail ken.wug@gmail.com* 2007-9-28 下午01:37:43*/public class HotSwapClassLoader extends URLClassLoader {     public HotSwapClassLoader(URL[] urls) {        super (urls);    }     public HotSwapClassLoader(URL[] urls, ClassLoader parent) {        super (urls, parent);    }     public Class load(String name)          throws ClassNotFoundException {        return load(name, false );    }     public Class load(String name, boolean resolve)          throws ClassNotFoundException {        if ( null != super .findLoadedClass(name))            return reload(name, resolve);         Class clazz = super .findClass(name);         if (resolve)            super .resolveClass(clazz);         return clazz;    }     public Class reload(String name, boolean resolve)          throws ClassNotFoundException {        return new HotSwapClassLoader( super .getURLs(), super .getParent()).load(            name, resolve);    }} public class A {    private B b;     public void setB(B b) {         this .b = b;    }     public B getB() {         return b;    }} public class B {}

這個類的作用是可以重新載入同名的類, 但是, 為了實現hotswap, 老的對象狀態
需要通過其他方式拷貝到重載過的類產生的全新執行個體中來。(A類中的b執行個體)

而新執行個體所依賴的B類如果與老對象不是同一個類載入器載入的, 將會拋出類型轉換異常(ClassCastException).

為瞭解決這種問題, HotSwapClassLoader自訂了load方法. 即當前類是由自身classLoader載入的, 而內部依賴的類還是老對象的classLoader載入的.

public class TestHotSwap {public static void main(String args[]) {    A a = new A();    B b = new B();    a.setB(b);     System.out.printf("A classLoader is %s n" , a.getClass().getClassLoader());    System.out.printf("B classLoader is %s n" , b.getClass().getClassLoader());    System.out.printf("A.b classLoader is %s n" ,   a.getB().getClass().getClassLoader());     HotSwapClassLoader c1 = new HotSwapClassLoader( new URL[]{ new URL( "file:\e:\test\")} , a.getClass().getClassLoader());    Class clazz = c1.load(" test.hotswap.A ");    Object aInstance = clazz.newInstance();     Method method1 = clazz.getMethod(" setB ", B.class);    method1.invoke(aInstance, b);     Method method2 = clazz.getMethod(" getB ", null);    Object bInstance = method2.invoke(aInstance, null);     System.out.printf(" reloaded A.b classLoader is %s n", bInstance.getClass().getClassLoader());}}

輸出

A classLoader is sun.misc.Launcher$AppClassLoader@19821f
B classLoader is sun.misc.Launcher$AppClassLoader@19821f
A.b classLoader is sun.misc.Launcher$AppClassLoader@19821f
reloaded A.b classLoader is sun.misc.Launcher$AppClassLoader@19821f

本文系轉載,原文連結:http://kenwublog.com/structure-of-java-class-loader

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.