面試題思考:如何編寫自己的類加載器


類加載器就是負責檢索並加載其他Java類或者資源(如文件)的對象,它一般繼承於java.lang.ClassLoader這個抽象類(除了BootstrapClassLoader)。

實際上,程序中所有的類都是通過類加載器進行加載的,並且它們都持有各自類加載器對象的引用,可以通過java.lang.Class的getClassLoader方法得到。

一個程序中的各個類加載器構成了一棵樹,位於根部的被稱作BootstrapClassLoader,它作為Java虛擬機的一部分,它使用C++語言實現,在程序剛啟動時就被加載進來,負責Java標准庫的加載,並且只有它能完成該任務。

  
標准擴展(Extension)類加載器負責加載Java_Home /lib/ext或者由系統變量 java.ext.dir指定位置中的類庫

  
應用程序(Application)類加載器負責加載系統類路徑(CLASSPATH)中指定的類庫。同時它常被稱為系統(System)加載器,因為我們可以通過getSystemClassLoader()方法來獲取它。

  
而由我們程序員自己編寫的類加載器被稱為自定義類加載器,如果生成自定義類加載器時沒有明確地指出父類加載器,會默認把應用程序(Application)類加載器作為自己的父親。

  
類加載器的父子關系相當重要,當你指定由一個類加載器加載某一個類時,它會無論如何先把它交給自己的父類加載器來執行,除非父類加載器檢索不到這個類,才會開始嘗試自己檢索和加載。

顯式使用類加載器的最常見例子就是使用JDBC的第一步——加載數據庫驅動,如:

Class.forName("com.mysql.jdbc.Driver");

或者

Class.forName("oracle.jdbc.driver.OracleDriver");

編寫目錄型類加載器的代碼

思路很簡單,把指定目錄追加到類加載器的類路徑中即可。

public static ClassLoader createClassLoader(String dirname) throws java.io.IOException {
    java.net.URL[] url = new java.net.URL[1];
    java.io.File file;
    if (dirname.endsWith("/")) {
        file = new java.io.File(dirname);
    }
    else {
        // 對於目錄的路徑,最后必須要有'/'
        file = new java.io.File(dirname + "/");
    }
    url[0]= file.toURI().toURL();

    ClassLoader parent = ClassLoader.getSystemClassLoader();
    java.net.URLClassLoader loader = new java.net.URLClassLoader(url, parent);

    return loader;
}

下面以一個實例演示如何使用該類加載器,首先創建一個class目錄的類加載器,然后獲取test.Main類對象,並調用它的main方法。

private void foo() throws Exception {
    ClassLoader loader = createClassLoader("./class/");
    Class<?> cls = Class.forName("test.Main", true, loader);
    java.lang.reflect.Method method = cls.getMethod("main", new Class[]{String[].class});

    method.invoke(null, new Object[]{null});
}

雖然這次演示的是目錄,但對於jar文件和zip文件同樣可以通過URLClassLoader來加載。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM