类加载器
类与类加载器
判断类是否“相等”
任意一个类,都由加载它的类加载器和这个类本身一同确立其在 Java 虚拟机中的唯一性,每一个类加载器,都有一个独立的类名称空间。
因此,比较两个类是否“相等”,只有在这两个类是由同一个类加载器加载的前提下才有意义,否则,即使这两个类来源于同一个 Class 文件,被同一个虚拟机加载,只要加载它们的类加载器不同,那么这两个类就必定不相等。
这里的“相等”,包括代表类的 Class 对象的 equals() 方法、isInstance() 方法的返回结果,也包括使用 instanceof 关键字做对象所属关系判定等情况。
加载器种类
常见 HotSpot 配置中的内置类加载器包括启动类加载器、平台类加载器和应用程序类加载器;名称及实现会随 JDK 版本变化:
- 启动类加载器(Bootstrap ClassLoader):负责加载虚拟机实现提供的基础类库。JDK 8 及更早版本中,部分类库来自
<JAVA_HOME>\lib下的rt.jar等文件;JDK 9 起,运行时映像不再使用rt.jar,不能把该目录布局当作通用规则。 - 平台类加载器(Platform ClassLoader):JDK 9 起取代扩展类加载器,负责加载平台类。JDK 8 及更早版本使用扩展类加载器(Extension ClassLoader),其扩展目录规则属于旧版实现。
- 应用程序类加载器(Application ClassLoader): 由于这个类加载器是 ClassLoader 中的
getSystemClassLoader()方法的返回值,所以一般也称它为“系统类加载器”。它负责加载用户类路径(classpath)上所指定的类库,开发者可以直接使用这个类加载器,如果应用程序中没有自定义过自己的类加载器,一般情况下这个就是程序中默认的类加载器。

当然,如果有必要,还可以加入自己定义的类加载器。
双亲委派模型
什么是双亲委派模型
双亲委派模型描述常见类加载器的层次关系:除了顶层启动类加载器外,其余加载器通常有父加载器(父子关系一般通过组合实现)。它是 Java 平台的默认委派约定,并非 JVM 对所有自定义类加载器的强制要求;自定义加载器可以改变委派策略。
工作过程
如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请求(找不到所需的类)时,子加载器才会尝试自己去加载。
在 java.lang.ClassLoader 中的 loadClass 方法中实现该过程。
为什么使用双亲委派模型
像 java.lang.Object 这些存放在 rt.jar 中的类,无论使用哪个类加载器加载,最终都会委派给最顶端的启动类加载器加载,从而使得不同加载器加载的 Object 类都是同一个。
相反,如果没有使用双亲委派模型,由各个类加载器自行去加载的话,如果用户自己编写了一个称为 java.lang.Object 的类,并放在 classpath 下,那么系统将会出现多个不同的 Object 类,Java 类型体系中最基础的行为也就无法保证。