自定义类加载器

发布时间 2024-01-11 20:39:26作者: 程序马2023

自定义类加载器只需要继承java.lang.ClassLoader类,该类有两个核心方法,一个是loadClass(String, boolean),实现了双亲委派机制,还有一个方法是findClass,默认实现是空方法,所以我们自定义类加载器主要是重写findClass方法。

public class MyClassLoaderTest {
    static class MyClassLoader extends ClassLoader{
        //指定类加载器加载哪个路径下的类
        private String classPath;

        public MyClassLoader(String classPath) {
            this.classPath = classPath;
        }
        //name为类的全限定名 (com.mafu.User) 把指定的路径下的.class文件读入到字节数组中
        private byte[] loadByte(String name) throws Exception {
            name = name.replace('.', '/');
            FileInputStream fileInputStream = new FileInputStream(classPath + "/" + name + ".class");
            int len = fileInputStream.available();
            byte[] data = new byte[len];
            fileInputStream.read(data);
            fileInputStream.close();
            return data;
        }
        
        //把.class文件二进制数组转为了一个Class对象
        @Override
        protected Class<?> findClass(String name){
            try {
                byte[] data = loadByte(name);
                return defineClass(name,data,0,data.length);
            } catch (Exception e) {
                e.printStackTrace();
                throw new RuntimeException(e);
            }

        }
    }

    //测试 main方法
  public static void main(String[] args) throws Exception {
    MyClassLoader classLoader=new MyClassLoader("D:/test");
    Class clazz=classLoader.loadClass("com.mafu.jvm.User");
    System.out.println(clazz.getClassLoader().getClass().getName());
    //打印结果为:com.mafu.jvm.MyClassLoaderTest$MyClassLoader
}
}

打破双亲委派机制

  //重写父类的loadClass方法,其实就把委托父类加载的逻辑代码去掉,用自己写的类加载器加载
   protected Class<?> loadClass(String name, boolean resolve)throws ClassNotFoundException{
        synchronized (getClassLoadingLock(name)) {
            Class<?> c = findLoadedClass(name);
            /**  去掉以下被注释的代码就不会向上委托给父类加载器去加载了
            if (c == null) {
                long t0 = System.nanoTime();
                try {
                    if (parent != null) {
                        c = parent.loadClass(name, false);
                    } else {
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                    // ClassNotFoundException thrown if class not found
                    // from the non-null parent class loader
                }
                */
                if (c == null) {
                    //检查到当前类未被加载过就进来执行以下代码
                    long t0 = System.nanoTime();
                    long t1 = System.nanoTime();
                    if(name.startsWith("com.mafu.jvm")){
                        //如果是自己的包(指定的包下的类)就直接加载打破双亲委派
                        c = findClass(name);
                    }else {
                        //否则其他的就走双亲委派加载机制
                        c = this.getParent().loadClass(name);
                    }
                    sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                    sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                    sun.misc.PerfCounter.getFindClasses().increment();
                }
           // }
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }
    }