溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

java實現(xiàn)自定義類加載器的方法

發(fā)布時間:2020-10-29 09:45:17 來源:億速云 閱讀:167 作者:小新 欄目:編程語言

這篇文章給大家分享的是有關(guān)java實現(xiàn)自定義類加載器的方法的內(nèi)容。小編覺得挺實用的,因此分享給大家做個參考。一起跟隨小編過來看看吧。

各類加載器雖然以父子相稱,但是沒有繼承關(guān)系

點入ClassLoader的源碼查看樣例:

* <blockquote><pre>
 *     class NetworkClassLoader extends ClassLoader {
 *         String host;
 *         int port;
 *
 *         public Class findClass(String name) {
 *             byte[] b = loadClassData(name);
 *             return defineClass(name, b, 0, b.length);
 *         }
 *
 *         private byte[] loadClassData(String name) {
 *             // load the class data from the connection
 *             &nbsp;.&nbsp;.&nbsp;.
 *         }
 *     }
 * </pre></blockquote>

只需繼承CalssLoader,重寫 findClass方法即可:

package reflect;
 
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
 
public class MyClassLoader extends ClassLoader{
 
    // 用于保存加載的文件的大小
    private int classSize; 
    // 新增的類加載路徑
    private static List<String> paths = new ArrayList<>();
 
    static {
        paths.add("D:\\Users\\jeff.chan\\Desktop\\");
    }
    // 默認會將app類加載器做為該類加載器的父加載器
    public MyClassLoader() {
    }
 
    public MyClassLoader(ClassLoader parent) {
        super(parent);
    }
 
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        byte[] b = loadBinaryData(name);
        // 打印執(zhí)行標(biāo)記
        System.out.println("use custom classloader...");
        return defineClass(name, b,0, classSize);
    }
 
    public byte[] loadBinaryData(String name) throws ClassNotFoundException{
        String pathName = name.replaceAll("\\.", "/");
        File file = null;
        for (String path : paths) {
            file = new File(path+pathName+".class");
            if(file.exists() && file.isFile()){
                break;
            }
        }
        if(file==null || !file.isFile()){
            throw  new ClassNotFoundException();
        }
        // 讀取文件的二進制信息
        try (InputStream in = new FileInputStream(file)){
            // 一般這個大小夠了,這里是為了方便讀取
            // 文件的內(nèi)容,所以一次性讀入,并且將大小返回
            // 用于defineClass
            byte[] b = new byte[1024 * 1024 * 10];
            classSize = in.read(b);
            return b;
        }catch (IOException ioException){
            ;
        }
        return null;
    }
}

這里加入了一個MyClassLoader自定義類加載器,掃描的路徑為:

D:\\Users\\jeff.chan\\Desktop\\

那么新加入的類加載器就和app類加載器,擴展類加載器,啟動類加載器一起起作用。

測試用例:

package reflect;
 
 
public class Person {
 
    private String name;
    private String age;
 
    public Person() {
    }
 
    public Person(String name, String age) {
        this.name = name;
        this.age = age;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public String getAge() {
        return age;
    }
 
    public void setAge(String age) {
        this.age = age;
    }
 
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age='" + age + '\'' +
                '}';
    }
}

客戶端:

package reflect;
 
public class Client {
 
    public static void main(String[] args) throws Exception {
        MyClassLoader classLoader = new MyClassLoader();
        Class<?> aClass = classLoader.loadClass("reflect.Person");
        System.out.println(aClass);
        System.out.println(aClass.getClassLoader());
    }
}

時直接運行代碼:那么會輸出

class reflect.Person
sun.misc.Launcher$AppClassLoader@18b4aac2

發(fā)現(xiàn)自己的類加載器根本不起作用。其實是因為雙親委托機制:

1、MyClassLoader 查看是否已經(jīng)加載 -》 2、App類加載查看是否已經(jīng)加載 -》3、 擴展類加載器查看是否已經(jīng)加載

-》 4、啟動類加載器查看是否已經(jīng)加載,沒有加載就嘗試加載 -》 5、擴展類嘗試加載 -》 6、app類加載嘗試加載 -》 7、MyClassLoader嘗試加載 -》 8、拋出找不到類的異常

上述的流程中,第6步會找到對應(yīng)的類,所以就直接返回了,根本沒有給MyClassLoader機會加載,所以才沒有調(diào)用自定義的類加載器MyClassLoader。

如果想要加載的話,那么就到編譯生成的Person.class移動到桌面reflect/Person.class下,執(zhí)行結(jié)果:

use custom classloader...
class reflect.Person
reflect.MyClassLoader@135fbaa4

結(jié)果發(fā)現(xiàn),自定義的類加載起作用了,其實就是上述的流程中的第7步,找到了相應(yīng)的類的二進制文件,加載了進來。

感謝各位的閱讀!關(guān)于java實現(xiàn)自定義類加載器的方法就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,讓大家可以學(xué)到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI