美文网首页
自定义类加载器

自定义类加载器

作者: kanaSki | 来源:发表于2019-07-11 20:47 被阅读0次
import java.io.*;

/**
 * 自定义文件系统类加载器
 * <p>
 * 自定义类加载器流程:
 * 1、继承:java.lang.ClassLoader
 * 2、首先检查请求的类型是否已经被这个类加载器装载到命名空间中,若已装载,直接返回
 * 3、委派类加载请求给父类加载器,如果父类加载器能够完成,则返回父类加载器加载的Class实例
 * 4、调用本类加载器的findClass方法,试图获取对应的字节码,如果能够获取到,则调用defineClass导入类型到方法区;
 * 如果获取不到对应的字节码或者其他原因失败,则返回异常给loadClass,loadClass转抛异常,终止加载过程
 * 注:被两个加载器加载的同一个类,JVM不认为是相同的类
 */
public class FileSystemClassLoader extends ClassLoader {
    private String rootDir;

    public FileSystemClassLoader(String rootDir) {
        this.rootDir = rootDir;
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        // 查找是否有已加载的类
        Class<?> loadedClass = findLoadedClass(name);
        if (loadedClass != null) {
            return loadedClass;
        } else {
            // 获得父类加载器
            ClassLoader parent = this.getParent();
            // 委派给父类加载
            try {
                loadedClass = parent.loadClass(name);
            } catch (Exception ex) {
            }
            if (loadedClass != null) {
                return loadedClass;
            } else {
                try {
                    byte[] classData = getClassData(name);
                    if (classData == null) {
                        throw new ClassNotFoundException();
                    } else {
                        loadedClass = defineClass(name, classData, 0, classData.length);
                        return loadedClass;
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return loadedClass;
        }
    }

    private byte[] getClassData(String name) throws IOException {
        String path = rootDir + "/" + name.replace('.', '/') + ".class";
        // 可以使用IOUtils将流中数据转为字节数组
        FileInputStream is = new FileInputStream(path);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte[] bytes = new byte[1024];
        BufferedInputStream br = new BufferedInputStream(is);
        int len = 0;
        while ((len = br.read(bytes)) != -1) {
            baos.write(bytes, 0, len);
            baos.flush();
        }
        byte[] byteArray = baos.toByteArray();
        baos.close();
        br.close();
        return byteArray;
    }

    public static void main(String[] args) throws ClassNotFoundException {
        FileSystemClassLoader loader = new FileSystemClassLoader("F:\\SpringBootProgram\\MyFirstWeb");
        Class<?> c = loader.loadClass("Hello");
        System.out.println(c);
    }
}

相关文章

网友评论

      本文标题:自定义类加载器

      本文链接:https://www.haomeiwen.com/subject/gusjkctx.html