类加载流程,类加载机制及自定义类加载器详解(面试再也不怕了) (5)

基于以上分析,我们简单重写findClass方法进行自定义类加载。

public class Hello {
   public void test(String str){
       System.out.println(str);
   }
}

public class MyClassloader extends ClassLoader {

    /**
     * 读取文件内容
     *
     * @param fileName 文件名
     * @return
     */

    private byte[] getBytes(String fileName) throws IOException {
        File file = new File(fileName);
        long len = file.length();
        byte[] raw = new byte[(int) len];
        try (FileInputStream fin = new FileInputStream(file)) {
            //一次性读取Class文件的全部二进制数据
            int read = fin.read(raw);
            if (read != len) {
                throw new IOException("无法读取全部文件");
            }
            return raw;
        }
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        Class clazz = null;
        //将包路径的(.)替换为斜线(/)
        String fileStub = name.replace(".""http://www.likecs.com/");
        String classFileName = fileStub + ".class";
        File classFile = new File(classFileName);

        //如果Class文件存在,系统负责将该文件转换为Class对象
        if (classFile.exists()) {
            try {
                //将Class文件的二进制数据读入数组
                byte[] raw = getBytes(classFileName);
                //调用ClassLoader的defineClass方法将二进制数据转换为Class对象
                clazz = defineClass(name, raw, 0, raw.length);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        //如果clazz为null,表明加载失败,抛出异常
        if (null == clazz) {
            throw new ClassNotFoundException(name);
        }
        return clazz;
    }

    public static void main(String[] args) throws Exception {
        String classPath = "loader.Hello";
        MyClassloader myClassloader = new MyClassloader();
        Class<?> aClass = myClassloader.loadClass(classPath);
        Method main = aClass.getMethod("test", String.class);
        System.out.println(main);
        main.invoke(aClass.newInstance(), "Hello World");
    }
}
//输出结果
//Hello World

ClassLoader还有一个重要的方法defineClass(String name, byte[] b, int off, int len)。此方法的作用是将class的二进制数组转换为Calss对象。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyjjxs.html