天天看點

深入分析ClassLoader原理



一、什麼是ClassLoader?

         大家都知道,當我們寫好一個Java程式之後,不是管是CS還是BS應用,都是由若幹個.class檔案組織而成的一個完整的Java應用程式,當程式在運作時,即會調用該程式的一個入口函數來調用系統的相關功能,而這些功能都被封裝在不同的class檔案當中,是以經常要從這個class檔案中要調用另外一個class檔案中的方法,如果另外一個檔案不存在的,則會引發系統異常。而程式在啟動的時候,并不會一次性加載程式所要用的所有class檔案,而是根據程式的需要,通過Java的類加載機制(ClassLoader)來動态加載某個class檔案到記憶體當中的,進而隻有class檔案被載入到了記憶體之後,才能被其它class所引用。是以ClassLoader就是用來動态加載class檔案到記憶體當中用的。

二、Java預設提供的三個ClassLoader

  1. BootStrap ClassLoader:稱為啟動類加載器,是Java類加載層次中最頂層的類加載器,負責加載JDK中的核心類庫,如:rt.jar、resources.jar、charsets.jar等,可通過如下程式獲得該類加載器從哪些地方加載了相關的jar或class檔案: [java]  view plain  copy
    1. URL[] urls = sun.misc.Launcher.getBootstrapClassPath().getURLs();  
    2. for (int i = 0; i < urls.length; i++) {  
    3.     System.out.println(urls[i].toExternalForm());  
    4. }  

    以下内容是上述程式從本機JDK環境所獲得的結果:

    file:/C:/Program%20Files/Java/jdk1.6.0_22/jre/lib/resources.jar

    file:/C:/Program%20Files/Java/jdk1.6.0_22/jre/lib/rt.jar

    file:/C:/Program%20Files/Java/jdk1.6.0_22/jre/lib/sunrsasign.jar

    file:/C:/Program%20Files/Java/jdk1.6.0_22/jre/lib/jsse.jar

    file:/C:/Program%20Files/Java/jdk1.6.0_22/jre/lib/jce.jar

    file:/C:/Program%20Files/Java/jdk1.6.0_22/jre/lib/charsets.jar

    file:/C:/Program%20Files/Java/jdk1.6.0_22/jre/classes/

    其實上述結果也是通過查找sun.boot.class.path這個系統屬性所得知的。 [java]  view plain  copy

    1. System.out.println(System.getProperty("sun.boot.class.path"));  
    列印結果:C:\Program Files\Java\jdk1.6.0_22\jre\lib\resources.jar;C:\Program Files\Java\jdk1.6.0_22\jre\lib\rt.jar;C:\Program Files\Java\jdk1.6.0_22\jre\lib\sunrsasign.jar;C:\Program Files\Java\jdk1.6.0_22\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.6.0_22\jre\lib\jce.jar;C:\Program Files\Java\jdk1.6.0_22\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.6.0_22\jre\classes
  2. Extension ClassLoader:稱為擴充類加載器,負責加載Java的擴充類庫,預設加載JAVA_HOME/jre/lib/ext/目下的所有jar。
  3. App ClassLoader:稱為系統類加載器,負責加載應用程式classpath目錄下的所有jar和class檔案。

        注意: 除了Java預設提供的三個ClassLoader之外,使用者還可以根據需要定義自已的ClassLoader,而這些自定義的ClassLoader都必須繼承自java.lang.ClassLoader類,也包括Java提供的另外二個ClassLoader(Extension ClassLoader和App ClassLoader)在内,但是Bootstrap ClassLoader不繼承自ClassLoader,因為它不是一個普通的Java類,底層由C++編寫,已嵌入到了JVM核心當中,當JVM啟動後,Bootstrap ClassLoader也随着啟動,負責加載完核心類庫後,并構造Extension ClassLoader和App ClassLoader類加載器。

三、ClassLoader加載類的原理

 1、原理介紹

       ClassLoader使用的是雙親委托模型來搜尋類的,每個ClassLoader執行個體都有一個父類加載器的引用(不是繼承的關系,是一個包含的關系),虛拟機内置的類加載器(Bootstrap ClassLoader)本身沒有父類加載器,但可以用作其它ClassLoader執行個體的的父類加載器。當一個ClassLoader執行個體需要加載某個類時,它會試圖親自搜尋某個類之前,先把這個任務委托給它的父類加載器,這個過程是由上至下依次檢查的,首先由最頂層的類加載器Bootstrap ClassLoader試圖加載,如果沒加載到,則把任務轉交給Extension ClassLoader試圖加載,如果也沒加載到,則轉交給App ClassLoader 進行加載,如果它也沒有加載得到的話,則傳回給委托的發起者,由它到指定的檔案系統或網絡等URL中加載該類。如果它們都沒有加載到這個類時,則抛出ClassNotFoundException異常。否則将這個找到的類生成一個類的定義,并将它加載到記憶體當中,最後傳回這個類在記憶體中的Class執行個體對象。