java類加載機制的一些自我總結

(首先聲明:這些文章都是自己的學習總結 寫出來只爲梳理自己的知識框架 也爲日後鞏固自身的java基礎之用 ,也希望能幫到愛好java的朋友,能力有限 有錯的地方歡迎大家提出來)

由於本人學java基礎是在linux環境下,所以這裏也是配合Linux環境講解的

啓動類加載器:.bootstrap class loader  加載Java的核心類,放在/opt/jdk1.7.0_45/jre/lib目錄下 全部是Java.開頭的jar包
擴展類加載器:.extensiable class loader 加載Java的擴展類  放在/opt/jdk1.7.0_45/jre/lib/ext目錄下 全部是Javax.開頭的jar包
系統類加載器:.system class loader(加載自己寫的類) 路徑指令CLASSPATH下的字節碼文件(編譯生成的.class文件,它保存類的信息)
網絡類加載器:.network class loader
自己寫的類若要加載成功,必須經過雙親委託機制,即:系統類加載器在加載自己寫的類的字節碼文件之前,先檢查上兩層加載器中加載的類中是否有類名相同的類,若有則不重複加載,若沒有本層才能加載成功
驗證如下:
  1.在bin目錄下把自己寫的類打成jar包:jar cvf hello.jar com
  2.刪掉com 則字節碼文件就不存在了:rm -r com
  3.直接運行:java com.briup.ch01.helloJava  //此時找不到要加載的類
  4.將這個類放入擴展類目錄下:sudo mv bin/hello.jar /opt/jdk1.7.0_45/jre/lib/ext/  //移動到系統目錄下而不是家目錄下需要超級用戶
  5.再運行這個類:java com.briup.ch01.helloJava //此時可以運行成功


注:將自己寫的類放入核心(或擴展類)目錄下有一定的壞處:如果忘記自己放進核心類或擴展類目錄中的類,下一次又寫了一個類名相同的類,無論怎麼改都不會有變化 
  6.所以需要刪掉:sudo rm -r hello.jar


這種機制導致一個寫程序時需要注意的地方:若有兩個類 class A  class B 若A的加載器級別比B高,類A調用類B A永遠找不到B 因爲類A只會找加載器級別與自己相同或者比自己高的類,不會去找比自己低的類
驗證如下:
   1.寫兩個類A、B A調用B
  package com.briup.ch01;
  public class A
  {
     public static void main(String[]args)
     {
         B.method();
      }
  }
  
  package com.briup.ch01;
  public class B
  {
     public static void method()
     {
        System.out.println("A call B");
      }
   }


  2.正常情況下肯定可以調用成功:javac -d bin src/A.java src/B.java  
                                java -cp bin com.briup.ch01.A
  3.若將A打成jar包放入擴展類目錄下:rm -r com/briup/ch01/B.class  //將B.class刪除
                                    jar cvf A.jar com             //將A打成jar包
                                    sudo mv A.jar /opt/jdk1.7.0_45/jre/lib/ext/   //將A的jar包放入擴展類目錄
                                    rm bin/com/briup/ch01/A.class    //將A.class刪除
  4.重新運行A則會出現類無法找到的異常:java com.briup.ch01.A  


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章