Java_動態重新加載Class總結


在此記載Java動態重新加載Class的點點滴滴,實現之前也在網上看了很多文章,但發現不是很清晰,后來發現總結,看源碼實現還是最靠譜。

直接上代碼:

package com.lkb.autoCode.util;

import com.lkb.autoCode.constant.AutoCodeConstant;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;

/**
 * DynamicClassLoader 動態類加載器
 *
 * @author Lilin
 * @date 2016/5/23
 */
public class DynamicClassLoader extends ClassLoader {

    private String classPath;

    public DynamicClassLoader(String classPath, ClassLoader parent) {
        super(parent);
        this.classPath = classPath;
    }

    @Override
    public Class<?> loadClass(String name) throws ClassNotFoundException {
        // 判斷當前加載的類是否是需要動態重新加載的類,
        // 假如是通過重寫的findClass在自定義的ClassLoader里面加載,
        // 假如不是就調用父ClassLoader默認加載
        if (name != null && name.equals(classPath)) {
            return findClass(name);
        }
        return super.loadClass(name, false);
    }

    /**
     * 根據類名查找class
     *
     * @param fullClassPath 類全路徑(包)
     * @return
     * @throws ClassNotFoundException
     */
    @Override
    protected Class<?> findClass(String fullClassPath)
            throws ClassNotFoundException {
        byte[] raw = readClassBytes(fullClassPath);
        // definClass方法參數說明:name:類包的全路徑如com.lkb.sb.client.shanghaiC.ShangHaiLoginClient
        //                         b:讀取的class文件的byte數組
        //                         off:從byte數組中讀取的索引
        //                         len:從byte數組中讀取的長度
        // 注:假如此類中有引入別的class類,如com.lkb.sb.client.BaseClient,循環執行findClass方法
        Class<?> clazz = defineClass(fullClassPath, raw, 0, raw.length);
        // 連接class
        resolveClass(clazz);
        return clazz;
    }

    /**
     * 讀取class
     *
     * @param fullClassPath
     * @return
     */
    private byte[] readClassBytes(String fullClassPath) {
        byte[] raw = null;
        InputStream stream = null;
        try {
            File file = new File(AutoCodeConstant.BASE_PATH + fullClassPath.replaceAll("\\.", "/") + AutoCodeConstant.CLASS_SUFFIX);
            stream = new FileInputStream(file);
            raw = new byte[(int) file.length()];
            stream.read(raw);
        } catch (Exception e) {

        } finally {
            try {
                stream.close();
            } catch (Exception e) {
            }
        }
        return raw;
    }

}

 

 

注:調用方式:

                // 通過自定義類加載器來加載
                // 獲取類的完成路徑
                String fullClassPath = getFullClassPath(AutoCodeConstant.CLIENT_PACKAGE, provinceCode, cityCode, AutoCodeConstant.LOGIN_CLIENT);
                // 父ClassLoader設為當前線程的ClassLoader,試過使用ClassLoader.getSystemClassLoader(),發現獲取的是系統級的,懶加載的類找不到
                dynamicClassLoader = new DynamicClassLoader(fullClassPath, Thread.currentThread().getContextClassLoader());
                loginInterface = (LoginInterface) dynamicClassLoader.loadClass(fullClassPath).getConstructor(new Class[]{CommonLoginSb.class, SbDefultModel.class}).newInstance(new Object[]{commonLoginSb, sbDefultModel});
                // 執行start方法
                resOutput = loginInterface.start(commonLoginSb.getMethod());

 


免責聲明!

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



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