写在前面

本文隶属于专栏《100个问题搞定Java虚拟机》,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢!

本专栏目录结构和文献引用请见100个问题搞定Java虚拟机

解答

当类加载器(Class-Loader)试图加载某个类型的时候,除非父加载器找不到相应类型,否则尽量将这个任务代理给当前加载器的父加载器去做。
使用委派模型的目的
1. 避免重复加载
2. 保障加载的安全性

补充

类加载器

启动类加载器(Bootstrap Class-Loader)

加载 jre/lib 下面的 jar 文件,如 rt.jar。

它是个超级公民,即使是在开启了 Security Manager 的时候,JDK 仍赋予了它加载的程序 AllPermission。

我们一般可以使用下面方法获取父加载器,但是在通常的 JDK/JRE 实现中,扩展类加载器 getParent() 都只能返回 null。

public final ClassLoader getParent()

扩展类加载器(Extension or Ext Class-Loader)

负责加载我们放到 jre/lib/ext/ 目录下面的 jar 包,这就是所谓的 extension 机制。

该目录也可以通过设置 “java.ext.dirs”来覆盖。

应用类加载器(Application or App Class-Loader)

负责加载应用程序路径下的类/classpath、系统变量java.class.path或者环境变量classpath指定的类。

类加载器

类加载机制的三个特征

双亲委派模型

不是所有类加载都遵守这个模型

有的时候,启动类加载器所加载的类型,是可能要加载用户代码的,比如 JDK 内部的 ServiceProvider/ServiceLoader机制,用户可以在标准 API 框架上,提供自己的实现,JDK 也需要提供些默认的参考实现。
例如,Java 中 JNDI、JDBC、文件系统、Cipher 等很多方面,都是利用的这种机制,这种情况就不会用双亲委派模型去加载,而是利用所谓的上下文加载器。

具体可以参考我的这篇博客——哪些情况下类加载不需要遵守双亲委派模型?

可见性

子类加载器可以访问父加载器加载的类型,但是反过来是不允许的,不然,因为缺少必要的隔离,我们就没有办法利用类加载器去实现容器的逻辑。

单一性

由于父加载器的类型对于子加载器是可见的,所以父加载器中加载过的类型,就不会在子加载器中重复加载。
但是注意,类加载器“邻居”间,同一类型仍然可以被加载多次,因为互相并不可见。

上一篇 下一篇