歡迎光臨
每天分享高質量文章

五分鐘看懂 ClassLoader

點選上方“芋道原始碼”,選擇“置頂公眾號”

技術文章第一時間送達!

原始碼精品專欄

 

java.lang.ClassLoader類概述:

從檔案中對ClassLoader類的介紹可以總結出這個類的作用就是根據一個指定的類的全限定名,找到對應的Class位元組碼檔案,然後載入它轉化成一個java.lang.Class類的一個實體.

類載入器的劃分:

啟動類載入器(Bootstrap ClassLoader):

 這個類載入器負責將\lib目錄下的類庫載入到虛擬機器記憶體中,用來載入java的核心庫,此類載入器並不繼承於java.lang.ClassLoader,不能被java程式直接呼叫,程式碼是使用C++編寫的.是虛擬機器自身的一部分.

擴充套件類載入器(Extendsion ClassLoader):
 這個類載入器負責載入\lib\ext目錄下的類庫,用來載入java的擴充套件庫,開發者可以直接使用這個類載入器.

應用程式類載入器(Application ClassLoader):

這個類載入器負責載入使用者類路徑(CLASSPATH)下的類庫,一般我們編寫的java類都是由這個類載入器載入,這個類載入器是CLassLoader中的getSystemClassLoader()方法的傳回值,所以也稱為系統類載入器.一般情況下這就是系統預設的類載入器.

除此之外,我們還可以加入自己定義的類載入器,以滿足特殊的需求,需要繼承java.lang.ClassLoader類.

  類載入器之間的層次關係如下圖:

用程式碼觀察一下類載入器:

package com.wang.test;

public class TestClassLoader {

    public static void main(String[] args) {
        ClassLoader loader = TestClassLoader.class.getClassLoader();
        System.out.println(loader.toString());
        System.out.println(loader.getParent().toString());
        System.out.println(loader.getParent().getParent());
    }
}

觀察列印結果:

sun.misc.Launcher$AppClassLoader@500c05c2
sun.misc.Launcher$ExtClassLoader@454e2c9c
null

第一行列印的是應用程式類載入器(預設載入器),第二行列印的是其父類載入器,擴充套件類載入器,按照我們的想法第三行應該列印啟動類載入器的,這裡卻傳回的null,原因是getParent(),傳回時null的話,就預設使用啟動類載入器作為父載入器.

 類載入器的雙親委派模型:

雙親委派模型是一種組織類載入器之間關係的一種規範,他的工作原理是:如果一個類載入器收到了類載入的請求,它不會自己去嘗試載入這個類,而是把這個請求委派給父類載入器去完成,這樣層層遞進,最終所有的載入請求都被傳到最頂層的啟動類載入器中,只有當父類載入器無法完成這個載入請求(它的搜尋範圍內沒有找到所需的類)時,才會交給子類載入器去嘗試載入.

這樣的好處是:java類隨著它的類載入器一起具備了帶有優先順序的層次關係.這是十分必要的,比如java.langObject,它存放在\jre\lib\rt.jar中,它是所有java類的父類,因此無論哪個類載入都要載入這個類,最終所有的載入請求都彙總到頂層的啟動類載入器中,因此Object類會由啟動類載入器來載入,所以載入的都是同一個類,如果不使用雙親委派模型,由各個類載入器自行去載入的話,系統中就會出現不止一個Object類,應用程式就會全亂了.

Class.forname()與ClassLoader.loadClass():

Class.forname():是一個靜態方法,最常用的是Class.forname(String className);根據傳入的類的全限定名傳回一個Class物件.該方法在將Class檔案載入到記憶體的同時,會執行類的初始化.

如: Class.forName(“com.wang.HelloWorld”);

ClassLoader.loadClass():這是一個實體方法,需要一個ClassLoader物件來呼叫該方法,該方法將Class檔案載入到記憶體時,並不會執行類的初始化,直到這個類第一次使用時才進行初始化.該方法因為需要得到一個ClassLoader物件,所以可以根據需要指定使用哪個類載入器.

如:ClassLoader cl=…….;cl.loadClass(“com.wang.HelloWorld”);



贊(0)

分享創造快樂