MDA/MDD/TDD/DDD/DDDDDDD
          posts - 536, comments - 111, trackbacks - 0, articles - 0
            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

          java類的加載

          Posted on 2011-02-24 17:58 leekiang 閱讀(422) 評論(0)  編輯  收藏 所屬分類: java
          打印Thread.currentThread().getContextClassLoader(),顯示如下:
          sun.misc.Launcher$AppClassLoader@19821f
          這個加載器是系統類加載器。ClassLoader.getSystemResourceAsStream("com/config.xml")使用的就是系統類加載器定位資源的。


          ??? //JDK1.6,java.lang.ClassLoader的loadClass(String?name,?boolean?resolve)方法的源碼
          protected?synchronized?Class<?>?loadClass(String?name,?boolean?resolve)
          ????
          throws?ClassNotFoundException
          ????{
          ????
          //?First,?check?if?the?class?has?already?been?loaded
          ????Class?c?=?findLoadedClass(name);
          ????
          if?(c?==?null)?{
          ????????
          try?{
          ????????
          if?(parent?!=?null)?{
          ?????????? //
          如果parent不為null,則調用parent的loadClass進行加載?
          ????????????c?=?parent.loadClass(name,?false);
          ????????}?
          else?{
          ?????????? //
          parent為null,則調用BootstrapClassLoader進行加載
          ????????????c?=?findBootstrapClassOrNull(name);
          ????????}
          ????????}?
          catch?(ClassNotFoundException?e)?{
          ????????????????
          //?ClassNotFoundException?thrown?if?class?not?found
          ????????????????
          //?from?the?non-null?parent?class?loader
          ???????? }
          ???????
          if?(c?==?null)?{
          ????????????
          //?If?still?not?found,?then?invoke?findClass?in?order to?find?the?class.
          ??????????? //
          如果仍然無法加載成功,則調用自身的findClass進行加載
          ????????????c?=?findClass(name);
          ????????}
          ????}
          ????
          if?(resolve)?{
          ????????resolveClass(c);
          ????}
          ????
          return?c;
          ????}

          java中共有三種類型的類加載器:
          ??? 1、引導(bootstrap)類加載器(用來加載java API類),例如加載java.lang.String類
          ??? 2、擴展類加載器(就是sun.misc.Launcher$ExtClassLoader,用來加載jre\lib\ext目錄下的jar包)
          ??? 3、系統類加載器(就是sun.misc.Launcher$AppClassLoader,主要用來加載CLASSPATH設置目錄中的Class)

          創建一個URLClassLoader,發現其父加載器(parent,注意不是父類)的類型為sun.misc.Launcher$AppClassLoader,而sun.misc.Launcher$AppClassLoader和sun.misc.Launcher$ExtClassLoader的父類都是URLClassLoader。AppClassLoader的父加載器是ExtClassLoader,ExtClassLoader的父加載器為null,即bootstrap類加載器。

          類加載有個雙親委托模式,
          AppClassLoader的父加載器是ExtClassLoader ,ExtClassLoader 的父加載器是bootstrap classloader,bootstrap 是C++寫的類加載器,會負責加載java核心類庫,就是jre/lib/rt.jar
          ExtClassLoader會加載擴展類庫,就是jre/lib/ext下的庫。

          雙親委托模式就是子加載器會先委托父加載器加載,父加載器加載不了子加載器才加載,
          這樣做避免了重復加載,也加強了java的安全了,防止了惡意加載器去加載核心庫。

          String?name?=?"com.domain.Account";
          ????????????
          ????????????URL?url1?
          =?new?URL("file:/D:/workspace/test/bin/");
          ????????????ClassLoader?cl?
          =?new?URLClassLoader(new?URL[]?{?url1?});
          ????????????Class?c1?
          =?cl.loadClass(name);
          ????????????
          ????????????URL?url2?
          =?new?URL("file:/D:/workspace/test/bin");
          ????????????ClassLoader?cl2?
          =?new?URLClassLoader(new?URL[]?{?url2?});
          ????????????Class?c2?
          =?cl2.loadClass(name);
          ????????????
          ????????????System.out.println(c1
          ==c2);//返回true,原因是都是用系統類加載器AppClassLoader加載的

          注意:
          1,在類A中使用Class.forName加載類B,那么加載類A的類加載器將會用于加載類B,這樣兩個類的類加載器是同一個。
          2,Class.forName("")和classLoader.load("")的區別主要是前者會做初始化,后者不會。見jdk注釋:A?call?to?forName("X")?causes?the?class?named?X?to?be?initialized.? 自己分別用兩種方式裝載一個帶靜態代碼的類就知道了。jdbc需要通過Class.forName("")的方式來裝載JDBC驅動程序(例如 Class.forName("com.mysql.jdbc.Driver"),之所以用Class.forName而沒有用 ClassLoader.load(),就是因為需要JVM完成Driver的初始化工作,而不僅僅是裝載),然后通過一個統一的工廠類 Java.sql.DriverManager來取得數據庫連接,并執行各種操作。Class.forName("")不僅load?class而且還保證resolve這個class,包括常量池解析,類初始化。。。這樣JDBC驅動使用這個方法,才能保證類里的靜態方法執行,一般驅動類的靜態方法會向DriverManager注冊自己,如果用classloader.load("")就不一定會resolve這個class,也就不能保證注冊驅動類!
          看了com.mysql.jdbc.Driver類的源碼,靜態代碼就一句:java.sql.DriverManager.registerDriver(new com.mysql.jdbc.Driver())
          3,

          參考
          1)java系統類加載器AppClassLoader之淺談 http://blog.sina.com.cn/s/blog_4db6a3f101000do1.html
          2)java類加載原理分析 http://gongmingwind.javaeye.com/blog/338366
          3)解讀ClassLoader http://www.javaeye.com/topic/83978
          4)http://xyiyy.javaeye.com/blog/362107

          Retrotranslator是一個Java字節碼轉換工具。它能夠把用JDK5.0編譯的Java Class轉換成可運行在JVM1.4
          主站蜘蛛池模板: 河池市| 汕头市| 阜康市| 马尔康县| 昆明市| 灵璧县| 宝兴县| 邢台市| 海盐县| 仙游县| 浙江省| 卢湾区| 呼玛县| 政和县| 包头市| 石楼县| 新竹县| 都匀市| 峨眉山市| 兴化市| 海原县| 牡丹江市| 肃北| 来宾市| 抚顺县| 阿拉善右旗| 奉节县| 张家港市| 陇西县| 将乐县| 扶绥县| 汉阴县| 广丰县| 贡嘎县| 焉耆| 宝山区| 嘉善县| 资源县| 宁远县| 惠东县| 永顺县|