双亲委派原则
三层类加载器介绍
**启动类加载器(Bootstrap Class Loader):**负责加载<JAVA_HOME>\lib 目录,或者被 -Xbootclasspath 参数制定的路径,例如 jre/lib/rt.jar 里所有的class文件。由C++实现,不是ClassLoader子类。
**拓展类加载器(Extension Class Loader):**负责加载Java平台中扩展功能的一些jar包,包括<JAVA_HOME>\lib\ext 目录中 或 java.ext.dirs 指定目录下的jar包。由Java代码实现。
**应用程序类加载器(Application Class Loader):**我们自己开发的应用程序,就是由它进行加载的,负责加载ClassPath路径下所有jar包。
简洁:java中,当一个类需要被加载时,会优先交给父类去加载,当父类加载不了(或没有父类时),再交给当前的加载器加载
代码示例
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException
{
// 首先要保证线程安全
synchronized (getClassLoadingLock(name)) {
// 先判断这个类是否被加载过
Class<?> c = findLoadedClass(name);
if (c == null) {
try {
// 有父类,优先交给父类尝试加载
if (parent != null) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
// 父类加载失败,这里捕获异常,但不需要做任何处理
}
if (c == null) {
// 没有父类,或者父类无法加载,尝试自己加载
c = findClass(name);
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
}
双亲委派机制的好处:
- 当我们需要加载一个类时,先判断父类能不能加载,这样就可以避免不同的加载器中加载了同一个类,但是我们在判断这两个类是否相等时,答案是不相等的
- 使用双亲委派模式,可以保证,每一个类只会有一个类加载器。例如Java最基础的Object类,它存放在 rt.jar 之中,这是 Bootstrap 的职责范围,当向上委派到 Bootstrap 时就会被加载。
在 rt.jar 之中,这是 Bootstrap 的职责范围,当向上委派到 Bootstrap 时就会被加载。 - 但如果没有使用双亲委派模式,可以任由自定义加载器进行加载的话,Java这些核心类的API就会被随意篡改。