主题切换
双亲委派模型
一、定义与加载流程
1. 核心规则
当一个类加载器收到加载类的请求时,不会自己先去加载,而是向上委托给父加载器处理;父加载器重复该逻辑,一直委托到顶层启动类加载器。 只有所有父加载器都无法加载该类时,当前子加载器才会尝试自己加载。
2. 完整流转顺序(以自定义类加载器加载Student为例)
- 自定义类加载器 → 委托父加载器AppClassLoader
- AppClassLoader → 委托父加载器ExtClassLoader
- ExtClassLoader → 委托父加载器BootStrap启动类加载器
- BootStrap查找
jre/lib,找不到Student类,向下退回 - ExtClassLoader查找
jre/lib/ext,找不到,退回 - AppClassLoader查找项目classpath,找到并加载Student
3. 核心类示例 String
我们自定义java.lang.String,加载请求会一路委托到BootStrap,它会加载rt.jar内原生String,不会使用我们自己写的类。
二、JVM采用双亲委派的两大作用
1. 保证类全局唯一,避免重复加载
父加载器成功加载后,子类不再重复加载同一个类,一个类在JVM中只存在一份Class对象,节省内存、防止类型转换异常。
2. 安全防护,防止篡改核心JDK类库
开发者无法自定义覆盖JDK核心类(如String、Object):
- 自定义
java.lang.String加载时,会先交给启动类加载器; - 启动类加载器加载原生rt.jar里的String;
- 自定义的类永远不会被加载,杜绝恶意代码篡改底层API。 示例:自己写带main方法的
java.lang.String,运行时报错:找不到main方法,因为执行的是原生无main的String。
三、面试简答
问:什么是双亲委派模型?为什么要设计这个机制? 答: 双亲委派是类加载器的加载规则:收到加载类请求时优先向上委托父加载器,顶层加载器找不到才由子类加载。 设计目的两点:
- 保证类唯一性,同一个类只会被加载一次,避免重复加载;
- 安全隔离,防止开发者自定义覆盖java.lang等核心基础类,保护JDK底层API不被篡改。