自定義ClassLoader

ClassLoader在Java中有著非常重要的作用,主要工作在Class裝載的加載階段,其主要作用是從系統(tǒng)外部獲得Class二進制數(shù)據(jù)流。它是Java的核心組件,所有的Class都是由ClassLoader進行加載的,ClassLoader負責將Class里的二進制數(shù)據(jù)流裝載進系統(tǒng),然后交給Java虛擬機進行連接,初始化等操作。

在加載階段,虛擬機需要完成以下三件事:

  1. 通過類的全限名獲取此類的二進制字節(jié)流。
  2. 將這個字節(jié)流所代表的靜態(tài)存儲結構轉換為方法區(qū)的運行時數(shù)據(jù)區(qū)
  3. 在內存中生成一個代表這個類的Class對象,作為方法區(qū)的這個類的各種數(shù)據(jù)訪問入口。

那么如何自定義ClassLoader呢?

其實只需要重寫findClass即可,findClass在找到Class對象后,調用defineClass來定義Class字節(jié)流。

代碼

  1. 先新建一個Java文件,在系統(tǒng)上的位置,然后用javac編譯java文件。
//編譯
//javac src/test/java/me/aihe/demo/Hello.java 
public class Hello {
    static {
        System.out.println("hello");
    }
}
  1. 新建ClassLoader,重寫findClass方法。
public class MyClassLoader extends ClassLoader {
    private String path;
    private String classLoaderName;

    public MyClassLoader(String path, String classLoaderName) {
        this.path = path;
        this.classLoaderName = classLoaderName;
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        try {

            byte[] b = loadClassData(name);
            return defineClass(name, b, 0, b.length);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    private byte[] loadClassData(String name) throws IOException {
        name = path + name + ".class";
        InputStream is = null;
        ByteArrayOutputStream outputStream = null;
        try {
            is = new FileInputStream(new File(name));
            outputStream = new ByteArrayOutputStream();
            int i = 0;
            while ((i = is.read()) != -1) {
                outputStream.write(i);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (outputStream != null) {
                outputStream.close();
            }
            if (is != null) {
                is.close();
            }
        }

        return outputStream.toByteArray();
    }
}
  1. 新建測試類,看看剛才寫的ClassLoader是否生效。
public class ClassLoaderChecker {
    
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        MyClassLoader myClassLoader = new MyClassLoader("/Users/aihe/Desktop/extra/spring-boot-learn/src/test/java/me/aihe/demo/", "random");
        Class c = myClassLoader.loadClass("Hello");
        System.out.println("ClassLoader:" + c.getClassLoader());
        Object instance = c.newInstance();
    }

}
  1. 運行查看結果,可以看到盡管Class文件是被我們自己的ClassLoader加載的,并且Class對象可以用來新建Java對象。


    image.png

最后

自定義類加載器有很多好處,它讓Java代碼更加靈活,應用場景:

  • 可以用來加密Class文件,然后解密Class文件進行再加載,提高系統(tǒng)安全性
  • 從網(wǎng)絡中加載Class文件

參考

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容