乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      Ken Wu's Blog ? java類加載器體系結(jié)構(gòu)(含hotswap原理)

       hero jack 2011-02-16

      java類加載器體系結(jié)構(gòu)(含hotswap原理)

      jvm classLoader architecture :

      a, Bootstrap ClassLoader/啟動(dòng)類加載器
      主要負(fù)責(zé)jdk_home/lib目錄下的核心 api 或 -Xbootclasspath 選項(xiàng)指定的jar包裝入工作.

      b, Extension ClassLoader/擴(kuò)展類加載器
      主要負(fù)責(zé)jdk_home/lib/ext目錄下的jar包或 -Djava.ext.dirs 指定目錄下的jar包裝入工作

      c, System ClassLoader/系統(tǒng)類加載器
      主要負(fù)責(zé)java -classpath/-Djava.class.path所指的目錄下的類與jar包裝入工作.

      b, User Custom ClassLoader/用戶自定義類加載器(java.lang.ClassLoader的子類)
      在程序運(yùn)行期間, 通過java.lang.ClassLoader的子類動(dòng)態(tài)加載class文件, 體現(xiàn)java動(dòng)態(tài)實(shí)時(shí)類裝入特性.

      類加載器的特性:

      1, 每個(gè)ClassLoader都維護(hù)了一份自己的名稱空間, 同一個(gè)名稱空間里不能出現(xiàn)兩個(gè)同名的類。
      2, 為了實(shí)現(xiàn)java安全沙箱模型頂層的類加載器安全機(jī)制, java默認(rèn)采用了 ” 雙親委派的加載鏈 ” 結(jié)構(gòu).
      如下圖:
      java class loader

      Class Diagram:
      classloader 類圖

      類圖中, BootstrapClassLoader是一個(gè)單獨(dú)的java類, 其實(shí)在這里, 不應(yīng)該叫他是一個(gè)java類。
      因?yàn)椋?它已經(jīng)完全不用java實(shí)現(xiàn)了。

      它是在jvm啟動(dòng)時(shí), 就被構(gòu)造起來的, 負(fù)責(zé)java平臺(tái)核心庫。(具體上面已經(jīng)有介紹)

      啟動(dòng)類加載實(shí)現(xiàn) (其實(shí)我們不用關(guān)心這塊, 但是有興趣的, 可以研究一下 ):
      bootstrap classLoader 類加載原理探索

      自定義類加載器加載一個(gè)類的步驟 :

      自定義類加載器加載一個(gè)類的步驟

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

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

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

      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 就是得到調(diào)用當(dāng)前forName方法的類的類加載器

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

      // Now create the class loader to use to launch the application
      try {
      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的無參構(gòu)造函數(shù)Launch()。
      使用線程上下文類加載器, 可以在執(zhí)行線程中, 拋棄雙親委派加載鏈模式, 使用線程上下文里的類加載器加載類.
      典型的例子有, 通過線程上下文來加載第三方庫jndi實(shí)現(xiàn), 而不依賴于雙親委派.
      大部分java app服務(wù)器(jboss, tomcat..)也是采用contextClassLoader來處理web服務(wù)。
      還有一些采用 hotswap 特性的框架, 也使用了線程上下文類加載器, 比如 seasar (full stack framework in japenese).

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

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

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

      自定義的類加載器實(shí)現(xiàn)
      defineClass(String name, byte[] b, int off, int len,ProtectionDomain protectionDomain)
      是java.lang.Classloader提供給開發(fā)人員, 用來自定義加載class的接口.

      使用該接口, 可以動(dòng)態(tài)的加載class文件.

      例如,
      在jdk中, URLClassLoader是配合findClass方法來使用defineClass, 可以從網(wǎng)絡(luò)或硬盤上加載class.

      而使用類加載接口, 并加上自己的實(shí)現(xiàn)邏輯, 還可以定制出更多的高級(jí)特性.

      比如,

      一個(gè)簡單的hot swap 類加載器實(shí)現(xiàn):

      import java.io.File;
      import java.io.FileInputStream;
      import java.lang.reflect.Method;
      import java.net.URL;
      import java.net.URLClassLoader;
       
      /**
      * 可以重新載入同名類的類加載器實(shí)現(xiàn)
      *
       
      * 放棄了雙親委派的加載鏈模式.
      * 需要外部維護(hù)重載后的類的成員變量狀態(tài).
      *
      * @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 {}

      這個(gè)類的作用是可以重新載入同名的類, 但是, 為了實(shí)現(xiàn)hotswap, 老的對(duì)象狀態(tài)
      需要通過其他方式拷貝到重載過的類生成的全新實(shí)例中來。(A類中的b實(shí)例)

      而新實(shí)例所依賴的B類如果與老對(duì)象不是同一個(gè)類加載器加載的, 將會(huì)拋出類型轉(zhuǎn)換異常(ClassCastException).

      為了解決這種問題, HotSwapClassLoader自定義了load方法. 即當(dāng)前類是由自身classLoader加載的, 而內(nèi)部依賴的類還是老對(duì)象的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

      轉(zhuǎn)載請(qǐng)注明原文鏈接:http:///structure-of-java-class-loader

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類似文章 更多