Java-Classloader-loadeClass(String,boolean)、findClass(String)类加载源码解析

来源:互联网 发布:高考改革 知乎 编辑:程序博客网 时间:2024/06/05 16:42

这里为了更好的说明类加载的过程,将部分次要代码删去,若有兴趣,可以自行查看Classloder源码

首先我们先来简述一下类加载的过程

  1. 使用findLoadedClass(name)方法查看该类是否已经被加载

  2. 如果该类未被加载过,则调用他的父类加载器,这里的父类加载器是扩展类加载器

  3. 扩展类加载器同样是继承ClassLoader类,因为它存在父类加载器就是引导类加载器,所以在执行loadClass方法时,同样会将加载委派给他的父类引导类加载器来执行

  4. 轮到引导类加载器的时候,由于它是加载器的最高一级,没有父类了,所以他就调用自身也就是引导类加载器的类加载方法

  5. 如果引导类加载不了,则会一层层往下退,先交给扩展类加载器,同理如果拓展类加载器还是加载不了,则会交给应用程序类加载类,如果还是加载不了,则最终会回到用户自定义的类加载器执行用户重写的findClass(String)方法

所以用户自定义类加载器的时候要重写findClass(String)方法而不是loadClass方法

protected Class<?> loadClass(String name, boolean resolve)            throws ClassNotFoundException        {            //同步锁保证类加载是线程安全的            synchronized (getClassLoadingLock(name)) {                //查看该类是否已经被加载                Class<?> c = findLoadedClass(name);                //该类未被加载过                if (c == null) {                    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) {                        // If still not found, then invoke findClass in order                        // to find the class                        //就调用自定义的类加载器来执行加载                        c = findClass(name);                    }                }                //如果确认该类已经被加载,则直接链接到指定的类                if (resolve) {                    resolveClass(c);                }                return c;            }        }
    //用户在自定义类加载器的时候通常需要继承java.lang.ClassLoader并重写该方法    //该方法会内loadClass(String,boolean)方法调用    protected Class<?> findClass(String name) throws ClassNotFoundException {        throw new ClassNotFoundException(name);    }