双亲委派机制

Catalogue   
  • Bootstrap ClassLoader:使用 C++实现,是虚拟机的一部分。它主要负责 加载存放在%JAVAHOME%/lib 目录中的,或者被-Xbootclasspath 指定的类库
    到虚拟机内存中,Bootstrap ClassLoader 无法被 java 程序直接引用。
  • Extension ClassLoader:主要负责加载%JAVAHOME%/lib/ext 目录中的, 或者被 java.ext.dirs 系统变量指定路径的所有类。
  • Application ClassLoader:也被称为系统类加载器(因为其实 getSystemClassLoader 的返回对象),主要负责加载用户类路径(ClassPath) 下的类库

工作流程讲解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
synchronized(this.getClassLoadingLock(name)) {
Class var4 = this.findLoadedClass(name);
// 检查需要加载的类是否已经被加载过
if (var4 == null) {
long var5 = System.nanoTime();

try {
// 若没有加载,则调用父加载器的 loadClass()方法
if (this.parent != null) {
var4 = this.parent.loadClass(name, false);
} else {
var4 = this.findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException name0) {
// 若父类加载器加载失败会抛出 ClassNotFoundException,
//说明父类加载器无法完成加载请求
}

if (var4 == null) {
long var7 = System.nanoTime();
// 在父类加载器无法加载时
// 再调用本身的 findClass 方法进行类加载
var4 = this.findClass(name);
PerfCounter.getParentDelegationTime().addTime(var7 - var5);
PerfCounter.getFindClassTime().addElapsedTimeFrom(var7);
PerfCounter.getFindClasses().increment();
}
}

if (resolve) {
this.resolveClass(var4);
}

return var4;
}
}

若一个类加载器收到了类加载请求:

  1. 把该类加载请求委派给父类加载器去完成,而不会自己去加载该类每层的类加载器都是如此,因此所有的加载请求最终都应传送到顶层的启动类加载器中
  2. 只有当父类加载器反馈自己无法完成该加载请求(它的搜索范围中没有找到所需的类)时,子加载器才会自己去加载