溫馨提示×

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

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

Java中自定義類加載器和動(dòng)態(tài)加載的示例分析

發(fā)布時(shí)間:2021-12-24 17:04:23 來源:億速云 閱讀:138 作者:小新 欄目:大數(shù)據(jù)

小編給大家分享一下Java中自定義類加載器和動(dòng)態(tài)加載的示例分析,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

自定義類加載器

我們需要一個(gè)自定義的類加載器,完成任何路徑包括網(wǎng)絡(luò)的文件加載,這個(gè)是取得 java 字節(jié)碼文件,也就是編譯后的 class 文件,他可能在世界的某個(gè)角落。
實(shí)現(xiàn)自定義的類加載器首先是繼承ClassLoader這個(gè)類,來看下構(gòu)造方法代碼

public class MyClassLoad extends ClassLoader {    private String rootPath;    public MyClassLoad(String rootPath) {        this.rootPath = rootPath;
    }
}

構(gòu)造方法,僅僅是把路徑傳入,也就是 class 文件的文件夾,不包括包名稱的路徑;
接下來重寫findClass方法;

/**
     * 根據(jù)name來尋找該類
     * 
     */
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        Class<?> c = findLoadedClass(name);        if (c == null) { // 內(nèi)存堆中還沒加載該類
            c = findMyClass(name); // 自己實(shí)現(xiàn)加載類
        }        return c;
    }

首先在內(nèi)存堆里面查找,沒有加載的話就到自己實(shí)現(xiàn),看下findMyClass方法

/**
     * 加載該類
     * 
     * @param name
     * @return
     */
    private Class<?> findMyClass(String name) {        try {            byte[] bytes = getData(name);            return this.defineClass(null, bytes, 0, bytes.length); // 調(diào)用父類方法,生成具體類
        } catch (Exception e) {
            e.printStackTrace();
        }        return null;
    }

該方法根據(jù)字節(jié)數(shù)組返回Class類,根據(jù) class 文件獲取字節(jié)數(shù)組可以使用Apache 文件操作相關(guān)輔助類,這里使用原生 jdk 實(shí)現(xiàn);

private byte[] getData(String className) {
        String path = rootPath + File.separatorChar + className.replace('.', File.separatorChar) + ".class";
        InputStream is = null;        try {
            is = new FileInputStream(path);
            ByteArrayOutputStream stream = new ByteArrayOutputStream();            byte[] buffer = new byte[2048];            int num = 0;            while ((num = is.read(buffer)) != -1) {
                stream.write(buffer, 0, num);
            }            return stream.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {            if (is != null) {                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }        return null;
    }

這個(gè)簡單的自定義類加載器就差不多了,如果需要實(shí)現(xiàn)自己加密解密的可以在字節(jié)數(shù)組里面進(jìn)行折騰,這里不再深入,我們的目標(biāo)是熱加載一段 java代碼,可能的解決方法是,構(gòu)建一個(gè) java 模板,里面內(nèi)置一些方法,外界可以增加一些新的方法,也可以調(diào)用內(nèi)置方法。

好!開始一個(gè)簡單的,把一段代碼加載到內(nèi)存并且執(zhí)行吧。

import java.io.File;import java.io.FileWriter;import javax.tools.JavaCompiler;import javax.tools.JavaCompiler.CompilationTask;import classload.MyClassLoad;import javax.tools.JavaFileObject;import javax.tools.StandardJavaFileManager;import javax.tools.ToolProvider;public class LoadJava {    public static final String javaCode = "package classload;public class HelloWorld2 {public HelloWorld2() {System.out.println(\"Hello World\");}}";    public static void runJavaCode() throws Exception {        // 把 java String 存儲(chǔ)到文件
        String fileName = "/Users/XXXXXXX/Documents/demo/java/classload/HelloWorld2.java";
        File file = new File(fileName);
        FileWriter fw = new FileWriter(file);
        fw.write(javaCode);
        fw.flush();
        fw.close();        //
        JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
        StandardJavaFileManager standardFileManager = javaCompiler.getStandardFileManager(null, null, null);
        Iterable<? extends JavaFileObject> iterable = standardFileManager.getJavaFileObjects(fileName);        // 執(zhí)行編譯任務(wù)
        CompilationTask task = javaCompiler.getTask(null, standardFileManager, null, null, null, iterable);
        task.call();
        standardFileManager.close();        // 把編譯后的 class 文件加載到內(nèi)存
        ClassLoader pcl = new MyClassLoad("/Users/XXXXXXX/Documents/demo/java/");
        Class c = pcl.loadClass("classload.HelloWorld2");
        System.out.println(c.newInstance());

    }    public static void main(String[] args) {        try {
            LoadJava.runJavaCode();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

以上是“Java中自定義類加載器和動(dòng)態(tài)加載的示例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問一下細(xì)節(jié)

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

AI