什么是双亲委派模型
双亲委派模型(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类加载器可以形成一个层次结构,提供了更好的类加载管理和隔离机制。