双亲委派模型(Parent-Delegation Model)是Java类加载器(ClassLoader)机制的一种实现方式。它是Java中实现类加载的一种层次结构模型。
双亲委派模型的工作过程是:在Java中,每个类加载器实例都有一个父类加载器(除了根加载器,它没有父类加载器)。当一个类加载器需要加载一个类时,它首先会委派给它的父类加载器去尝试加载。只有当父类加载器无法加载该类时,子加载器才会尝试加载类。
这个委派过程会一直向上追溯,直到达到根加载器。根加载器是Java虚拟机内置的类加载器,它负责加载Java核心类库(如java.lang
包下的类)和其他被系统类加载器委派的类。如果根加载器无法加载类,那么子加载器会尝试使用自己的加载机制加载类。
双亲委派模型的实现:
protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
// 首先,检查请求的类是否已经被加载过了
Class c = findLoadedClass(name);
if (c == null) {
try {
if (parent != null) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
// 如果父类加载器抛出ClassNotFoundException
// 说明父类加载器无法完成加载请求
}
if (c == null) {
// 在父类加载器无法加载时
// 再调用本身的findClass方法来进行类加载
c = findClass(name);
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
先检查请求加载的类型是否已经被加载过,若没有则调用父加载器的loadClass()方法,若父加载器为空则默认使用启动类加载器作为父加载器。假如父类加载器加载失败,抛出ClassNotFoundException异常的话,才调用自己的findClass()方法尝试进行加载。
这种双亲委派模型的设计有以下几个好处:
-
避免类的重复加载:当一个类加载器要加载一个类时,它会首先委派给父类加载器,如果父类加载器能够加载成功,就没有必要再由子加载器加载,这样可以避免同一个类被多个加载器重复加载的问题。
-
安全性:由于每个加载器只能加载自己的类和其父加载器委派的类,因此可以控制类的加载权限。核心类库由根加载器加载,防止被恶意篡改。
-
统一性:这种加载模型保证了类的一致性。无论由哪个加载器加载的类,得到的都是同一个类的唯一实例。
通过双亲委派模型,Java类加载器可以形成一个层次结构,提供了更好的类加载管理和隔离机制。