JVM-类加载器子系统
JVM——类加载器子系统
类加载器子系统:负责从文件系统/网络中加载class文件
1. 类加载器分类
- 启动类加载器Bootstrap ClassLoader
- 扩展类加载器Extension ClassLoader
- 系统类加载器AppClassLoader
- 用户自定义加载器
除Bootstrap CLassLoader,其他类加载器都继承于ClassLoader
2. 双亲委派机制
- 一个类加载器收到了类加载请求,先把请求一层层向上面的父类加载器委托,直到Bootstrap ClassLoader
- 若父类可加载则直接返回,否则向下层子加载器分配任务
- 若分配至AppClassLoader也无法加载,抛出ClassNotFound异常
双亲委派机制作用
- 避免类重复加载
- 防止核心API被篡改

当执行main方法的时候,会出现如下问题:

可想而知,编译器根据包名一层一层的向上请求,在请求 bootstrap classloader加载器的时候, bootstrap classloader发现自己可以加载java.lang包下的String类,所以对类库中的String进行了加载,但是类库中的String类并没有main方法,所以抛出了上述异常。
判断两个类是否为同一个类
- 完整类名相同
- 加载该类的类加载器相同
打破双亲委派机制
自定义ClassLoader并且重写loadClass方法。为什么需要打破双亲委派机制:
在一个 Web 容器(如 Tomcat)中,可能同时部署了两个 Web 应用 A 和 B。
- 问题:应用 A 需要 Spring 4.0,应用 B 需要 Spring 5.0。
- 冲突:如果遵循双亲委派,共同的父类加载器加载了其中一个版本的 Spring,另一个应用就无法加载自己需要的版本了。
- 解决:Tomcat 为每个 Web 应用创建了独立的
WebAppClassLoader,它会打破常规,优先加载应用自身目录下的类(WEB-INF/classes),从而实现不同应用间的类库隔离。
自定义类加载器
继承ClassLoader并且重写findClass方法。loadClass 是负责协调委派流程的“管理者”,而 findClass 是负责去具体地方找字节码的“打工人”:
loadClass是类加载的入口方法,它定义了加载的策略(即双亲委派机制)。- 默认行为:它会先检查类是否已加载,如果没有,就问父加载器要;父加载器要不到,才调用自己的
findClass。 - 重写它的目的:通常是为了打破双亲委派机制(例如 Tomcat 想要先加载自己的类,而不是先问父类)。
- 默认行为:它会先检查类是否已加载,如果没有,就问父加载器要;父加载器要不到,才调用自己的
findClass是 JDK 1.2 之后为了不破坏双亲委派而专门设计的扩展点。- 默认行为:在基类
ClassLoader中,它直接抛出ClassNotFoundException。 - 重写它的目的:在遵循双亲委派机制的前提下,告诉加载器如何去非标准路径(如数据库、网络、加密文件)获取类的字节码。
- 默认行为:在基类
JVM-类加载器子系统
http://example.com/2025/05/16/JVM-类加载器子系统/