了解双亲委派前,我们需要先了解下类加载器。
什么是类加载器呢
在Java中,类加载器(ClassLoader)负责将类文件加载到Java虚拟机中,并生成对应的 Class 对象。类加载器的分类和对应的作用如下:
-
启动类加载器(Bootstrap Class Loader):
- 作用:负责加载Java的核心类库,如
java.lang
包中的类。 - 实现:由C++编写,是虚拟机自身的一部分,不是Java类,无法直接获取对应的Java对象。
- 作用:负责加载Java的核心类库,如
-
扩展类加载器(Extension Class Loader):
- 作用:负责加载Java的扩展类库,位于
<JAVA_HOME>/lib/ext
目录下。 - 实现:是
sun.misc.Launcher$ExtClassLoader
类的实例,是Java实现的类加载器。
- 作用:负责加载Java的扩展类库,位于
-
应用程序类加载器(Application Class Loader):
- 作用:也称为系统类加载器,负责加载应用程序classpath下的类。
- 实现:是
sun.misc.Launcher$AppClassLoader
类的实例,是Java实现的类加载器。
-
自定义类加载器:
- 作用:允许开发者自定义类加载器,可以用于动态加载类,实现类的热部署、代码加密等功能。
- 实现:继承自
java.lang.ClassLoader
类,通过重写findClass()
方法实现类加载逻辑。
-
代理类加载器:
- 作用:用于委派给其他类加载器加载类,主要用于安全策略的实现。
- 实现:继承自
java.lang.SecurityManager
类,通过设置系统属性java.security.manager
启用安全管理器,从而使用代理类加载器。
-
合成类加载器:
- 作用:在模块化系统中,负责将不同模块的类加载到虚拟机中,以实现模块之间的隔离和交互。
- 实现:在Java 9及更高版本中引入的模块化系统中使用。
这些不同的类加载器按照优先级和责任范围有着不同的作用,通过组合使用,Java应用程序可以实现灵活的类加载机制,并根据不同的需求加载不同来源的类文件。
什么是双亲委派机制,如何打破双亲委派
双亲委派机制是Java类加载器的一种工作机制,其核心思想是当一个类加载器收到加载类的请求时,它首先不会自己去尝试加载这个类,而是将这个请求委派给父类加载器去完成。这样的层层委派一直递归到顶层的启动类加载器,只有当父类加载器无法完成加载请求时,子类加载器才会尝试自己去加载类。
打破双亲委派机制意味着在子类加载器尝试加载类时,不再委派给父类加载器,而是自己尝试加载。通常情况下,打破双亲委派机制可以通过自定义类加载器并重写 loadClass()
方法来实现。在自定义类加载器中,可以在加载类的过程中实现一些特殊逻辑,例如从特定位置加载类、对加载的类进行加密解密等。
需要打破双亲委派机制的情景包括但不限于:
-
热部署:在应用程序运行过程中更新类文件而不需要重启应用程序。此时需要自定义类加载器以便能够动态加载新版本的类文件,而不受双亲委派机制的限制。
-
动态代理:某些动态代理框架需要动态生成类并加载到虚拟机中,此时可能需要打破双亲委派机制以便在特定的类加载器中加载动态生成的类。
-
模块化系统:在模块化系统中,可能需要自定义类加载器以实现模块之间的隔离和交互。在这种情况下,自定义类加载器可能需要打破双亲委派机制以实现不同模块间的类加载。
需要注意的是,打破双亲委派机制可能会引入一些潜在的问题和安全风险,因此在使用时需要谨慎考虑,并确保了解清楚自定义类加载器的工作原理和潜在影响。