类加载器
🙈 BootstrapClassLoader
启动类加载器,最顶层的加载类,由 C/C++ 实现。
负责加载:
%JAVA_HOME%/lib
目录下的 jar 包和类- 被
-Xbootclasspath
参数指定的路径中的所有类。
🙉 ExtensionClassLoader
扩展类加载器。
是一种 Java 系统类库的扩展机制。负责加载 %JRE_HOME%/lib/ext
目录下的 jar 包和类,或被 java.ext.dirs
系统变量所指定的路径下的 jar 包。
🙊 ApplicationClassLoader
面向用户的加载器,负责加载当前应用 classpath
下的所有 jar 包和类。
双亲委派模型
每个类加载器都有自己的命名空间,用不同的类加载器加载了同一个限定名的类,JVM 也会认为是两个不同的类。
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 (getClassLoadingLock(name)) {
// (1) 判断是否加载过该类
Class<?> c = findLoadedClass(name);
if (c == null) {
long t0 = System.nanoTime();
try {
if (parent != null) {
c = parent.loadClass(name, false);
} else {
// (2) parent == null 约定为:parnet 为 Bootstracp ClassLoader
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
// ClassNotFoundException thrown if class not found
// from the non-null parent class loader
}
if (c == null) {
// (3) 说明 parent 加载不了,当前 loader 尝试加载 class
long t1 = System.nanoTime();
c = findClass(name);
// this is the defining class loader; record the stats
sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
sun.misc.PerfCounter.getFindClasses().increment();
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
}
|
默认情况下,一个限定名的类只会被一个类加载器加载并解析使用,在程序中是唯一的,不会产生歧义。
在加载时,首先会判断当前类是否被加载过,如果已经加载,会直接返回,否则才会尝试加载。
尝试加载时,不会自己进行加载,而是将请求委派给父类加载器,当父类加载器无法加载时,才会由自己处理。