加载的class如下:

package org.zhire.demo.myclass;

import cn.hutool.core.io.FileUtil;
import org.zhire.sharecode.UserDto;

/**
 * 自定义类加载器
 *
 * @Date 2021/9/26 7:52 下午
 * @Author chenqi
 */
public class MyClassLoader extends ClassLoader {
  
    public MyClassLoader(ClassLoader loader) {
        super(loader);
    }
  
    @Override
    public Class<?> loadClass(String name) {
        // 先判断要加载的类是不是已经被jvm加载过了
        Class<?> loadedClass = this.findLoadedClass(name);
        if (loadedClass != null) {
            System.out.println("已经被加载过了");
            return loadedClass;
        }
        // 先用ext加载器,为啥用它,因为需要加载java.开头的文件,它肯定不会加载我们指定的类,所以第一次加载肯定是空
        ClassLoader parent = ClassLoader.getSystemClassLoader().getParent();
        Class<?> clazz = null;
        try {
            clazz = parent.loadClass(name);
        } catch (ClassNotFoundException e) {
            // ext加载不到没关系,忽略
        }
        if (clazz == null) {
            // 正常情况这里应该是扫描路径下的包,这里就写一个固定的class文件
            byte[] bytes = FileUtil.readBytes("/.../UserDto.class");
            // 加载到jvm
            return defineClass(name, bytes, 0, bytes.length);
        } else {
            return clazz;
        }
    }
  
  /**
     * 如上所示一个简单的自定义类加载器就完成了
     *
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        // appClassLoader 加载
//        ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
//        Class<?> aClass = systemClassLoader.loadClass("org.zhire.sharecode.UserDto");
//        System.out.println(aClass.getClassLoader());

        MyClassLoader classLoader = new MyClassLoader(MyClassLoader.class.getClassLoader());
        try {
            Class<?> aClass = classLoader.loadClass("org.zhire.sharecode.UserDto");
            System.out.println(aClass.getClassLoader());

            UserDto dto = new UserDto();
            System.out.println(dto.getClass().getClassLoader());
            // 这里为啥是FALSE,按上面的流程来说,我自己的类加载器已经加载过了该对象啊,为啥我new出来的对象和自己加载的类对象不一样呢
            // 这是因为new对象的时候也会先判断该对象有没有被加载了,类在jvm里面的唯一标识是类加载器加上类的名称,
            // 我们new出对象是Appclassloader加载的,但是jvm里面并没有被加载,所以要new对象的时候用Appclassloader加载到jvm里面去。
            System.out.println(dto.getClass().equals(aClass));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
最后修改:2021 年 10 月 03 日 09 : 37 PM