双亲委派机制

双亲委派机制

双亲委派的原理:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委托给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到顶层的启动类加载器中。
只有当父类加载器反馈自己无法完成这个加载请求(它的搜索范围中没有找到所需要加载的类)时,子加载器才会尝试自己去加载。这种从下往上委托,再从上向下加载的过程叫作双亲委派机制。

双亲委派的意义:Java类随着类加载器具备了一种带有优先级的层次关系。例如类java.lang.Object,它存放在rt.jar之中,无论哪一个类加载器要加载这个类,最终都是委托给处于模型最顶端的启动类加载器进行加载,因此Object类在程序的各种加载器环境中都是同一个类。

相反,如果没有使用双亲委托模型,直接由接到加载请求的类加载器去加载,如果用户自己编写了一个称为java.lang.Object的类,并放在程序的ClassPath中,那系统中将会出现多个不同的Object类,Java类型体系中最基础的行为也就无法保证,应用程序也将会变得一片混乱。有了双亲委派机制,如果自己去编写一个rt.jar类库中同名的类,它将只能被编译,永远无法被加载。

2.2.1  双亲委派机制的实现

双亲委派由顶层父类加载器ClassLoader的loadClass(String name,boolean resolve)方法实现,其内部包含如下两个操作:

a.调用findLoadedClass(String name)检查当前类是否已被加载,若已被加载则直接返回该类的class对象;

b.调用当前类加载器的父类加载器loadClass方法,若父类加载器为空则调用启动类加载器进行加载,当启动类加载器反馈自己无法完成这个加载请求时,在由上至下调用各级类加载器的findClass(String name)方法进行类加载。

protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
    // First, check if the class has already been loaded 首先确认这个类是否已经加载 如果已经加载直接返回
    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;
}

注意:布尔型参数resolve表示是否在加载过程中便解析该类。

 自定义类加载器

JVM中,除了启动类加载器之外所有的类加载器都是ClassLoader的子类,开发者可以通过扩展ClassLoader,并重写protected Class<?> findClass(String name)方法实现自定义类加载器。

 

posted @ 2021-06-21 11:45  luxuewu  阅读(267)  评论(0编辑  收藏  举报