双亲委派模型(Parent-Delegation Model)是Java类加载器的工作机制。它要求除了启动类加载器(Bootstrap ClassLoader)外,其余的类加载器都应该有自己的父类加载器。
它的工作原理是:如果一个类加载器收到了类加载请求,它首先不会自己去尝试加载这个类,而是把该请求委派给父类加载器去完成。每一个层次的类加载器都是如此,只有当父类加载器在自己的搜索范围内无法找到所需类时,才会尝试自己去完成加载工作。
双亲委派模型的主要作用有:
- 避免类的重复加载:通过委派规则,除非父类加载器无法加载某个类,子加载器否则不会重复加载,从而避免冲突。
- 保证核心库的安全:启动类加载器专门用于加载Java核心库,如果其他类加载器可以随意加载这些类,很可能会产生安全漏洞。双亲委派模型可以避免这种情况的发生。
- 层次隔离:每一层类加载器都有自己loading的范围,使用双亲委派模型可以很好地实现不同层次的加载器之间的隔离。
来看一个简单例子:我们可以编写两个Java程序来模拟双亲委派模型的工作过程。
public class ParentDelegationModelTest {
public static void main(String[] args) {
//启动类加载器加载String类
String s = "Hello";
//自定义类加载器,它的父类加载器是系统类加载器
MyClassLoader classLoader = new MyClassLoader();
//尝试使用自定义类加载器加载String类
try {
Class<?> clazz = classLoader.loadClass("java.lang.String");
} catch (ClassNotFoundException e) {
//自定义类加载器无法加载String类,需要委派给父类加载器
System.out.println("需要委派给系统类加载器!");
}
}
}
class MyClassLoader extends ClassLoader {
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
//如果调用loadClass方法,就会调用findClass方法进行类加载
throw new ClassNotFoundException();
}
}
输出:
需要委派给系统类加载器!
我们可以看到,自定义类加载器由于遵循双亲委派模型,并不会重复加载String类,而是委派给父类加载器即系统类加载器去完成加载。
所以,双亲委派模型是Java类加载机制的基石,深入理解其工作原理与作用,可以帮助我们解决程序中出现的各种类加载相关问题。