双亲委派模型

从Java虚拟机的角度来看,类加载器只有两种:

  • 启动类加载器,由C++实现,作为虚拟机本身的一部分;
  • 其他类加载器,由Java实现,独立于虚拟机,且全部继承自抽象类java.lang.ClassLoader.

从开发人员的角度来看,类加载器可以再细分一点:

  • 启动类加载器:

    负责加载JAVA_HOME/lib下的类库,或者通过-Xbootclasspath指定的路径,且只能够加载被虚拟机识别的文件名,如果随便放入一个test.jar于这个目录下,也不会被启动类加载器加载,无法被Java程序直接引用,如图:

在这里插入图片描述

  • 扩展类加载器:

    负责加载JAVA_HOME/lib/ext目录中类库,或者被java.ext.dirs系统变量指定的路径下的类库,开发者可以直接使用扩展类加载器。

  • 应用程序类加载器:

    负责加载用户路径上所指定的类库,默认就是系统的类加载器。

  • 自定义类加载器:

    必要情况下, 也可以自定义类加载器。

双亲委派模型

类加载器之间的关系如图所示:

在这里插入图片描述

这种层次关系就是双亲委派模型,除了顶层的启动类加载器,其他的类加载都有自己的父亲类加载器,它的工作过程如下:

  1. 当自定义类加载器收到了一个加载请求,不会自己直接去加载这个请求,而是将请求交给应用程序类加载器;
  2. 应用程序类加载器同样不会直接加载,而是将请求交给扩展类加载器;
  3. 扩展类加载器将请求交给启动类加载器,如果启动类加载器能够找到所需要的类,那么就自己去处理这个请求,如果无法找到,那么就将请求回传给下一级,同理,下一级类加载的处理也同理。

为什么使用双亲委派模型

好处是显而易见的,例如,当我们要加载java.lang.Object这个类时,由于它是放在JAVA_HOME\lib\rt.jar之中,那么它的加载过程,从上面的过程可以知道,无论是哪一个类加载器来加载它,最终会交给启动类加载器来加载,这样就能够保证Object类不管在哪个加载器环境下都是指的同一个类,避免了如果用户自己编写了一个java.lang.Object,并放在自己的classPath下,导致一个程序中出现多个Object类,使得Java类型体系出现了混乱的行为。如果实现一个自定义加载器,强行用defineClass()去加载一个"java.lang"开头的类也不会成功,会收到虚拟机抛出的一个SecurityException异常。

双亲委派模型的实现

实现很简单,从ClassLoader的loadClass()就可以看到双亲委派的实现过程:

 protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException
    {
            // 1. 首先检查该类是否已经加载过了,如果加载过了,直接返回,否则就进入下面的双亲委派过程
            Class<?> c = findLoadedClass(name);
            if (c == null) {
                try {
                    if (parent != null) {
                       //2. 如果父类加载不为空,则请求父类加载器去加载
                        c = parent.loadClass(name, false);
                    } else {
                       //3.如果父类加载器为空,说明是启动类加载器,即是Bootstrap加载器,那么请求它去加载
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                   //如果父类加载无法完成加载请求,则抛出ClassNotFoundException异常。
                }
					//4.如果父类加载器无法加载时,调用自身类加载器去加载
                if (c == null) {
                    c = findClass(name);
                }
            }
            return c;
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值