知识点深化 · JVM · 类加载
类加载机制:双亲委派、加载-连接-初始化
一个 .class 文件到能被运行,要经过加载→验证→准备→解析→初始化。类加载器用双亲委派机制:先让父加载器尝试,自己实在加载不了才上。这一页把生命周期五阶段和双亲委派讲透。
① 小白第一课怎么学(4 步走,约 60 分钟)
别急着背代码,先按这四步建立直觉:
1看图建立直觉(10 分钟)
读②③:class 文件如何被 JVM 吃下。
2记五阶段(15 分钟)
读④:加载连接初始化。
3手推委派(20 分钟)
精读⑤。
4刷题纠错(15 分钟)
做⑦⑩,错题回⑥。
本课小目标学完你要能:① 说出类加载五阶段;② 解释双亲委派流程和好处;③ 说出自定义类加载器时机。
② 一图看懂:类加载全地图
读法:中心是类加载,左生命周期阶段右委派机制,下是应用与易错。
③ 本质直觉:class 文件从磁盘到 JVM 内存的五站旅程
加载:把 .class 字节码读进来,在堆里生成一个代表该类的 java.lang.Class 对象。
连接:① 验证——检查字节码合法;② 准备——给 static 变量分配内存并赋零值(不是你写的初始值);③ 解析——常量池符号引用转直接引用。
初始化:真正执行 static 代码块和 static 变量赋值。这是类加载的最后一步。
双亲委派:加载请求先委托给父加载器,父加载不了自己才加载。层层向上到启动类加载器。
双亲委派的好处核心类(如 java.lang.String)永远被启动类加载器加载,用户写个假 String 也顶替不了——安全。同个类只加载一次,避免重复。
④ 完整体系与对比表
生命周期五阶段
| 阶段 | 做什么 |
| 加载 | 读 class 字节码,生成 Class 对象 |
| 验证 | 检查字节码格式合法 |
| 准备 | static 变量分配内存,赋零值 |
| 解析 | 符号引用→直接引用 |
| 初始化 | 执行 static 块和赋值 |
三层类加载器
| 加载器 | 加载什么 |
| 启动类加载器 Bootstrap | JRE/lib 核心类(rt.jar) |
| 扩展类加载器 Extension | JRE/lib/ext 扩展类 |
| 应用类加载器 Application | classpath 下用户类 |
⑤ 用法场景与典型例题
例1(准备 vs 初始化)static int a=10; 准备阶段 a 的值?
准备赋零值。
准备阶段 static int 赋零值 0;初始化阶段才真正赋 10。答案:0。
例2(委派)用户自己写一个 java.lang.String 会怎样?
双亲委派先给启动类加载器。
加载请求向上委派,启动类加载器用 JDK 自带的 String,用户写的根本加载不进去——防篡改。
例3(触发初始化)什么时候触发初始化?
new、静态方法、静态字段赋值等。
new 对象、调用静态方法/字段、反射、子类初始化触发父类等,都是主动初始化时机。
做题心法准备零值初始化真赋值,这是高频考点。双亲委派先向上问,问不到自己才干。
⑥ 高频错误诊断(4 条)
错误1:准备阶段就赋写的初值准备只赋零值,写的 a=10 在初始化阶段才执行。
错误2:以为双亲委派是子先加载顺序反了:先向上委派父加载,父加载失败才自己加载。
错误3:自定义类加载器要重写 loadClass破坏委派要重写 loadClass;遵守委派重写 findClass 即可。
错误4:以为类加载只发生一次热部署、自定义容器会让同一类被不同加载器加载多次。
⑦ 考点真题演练(4 题)
考点分布
| 考法 | 出题形式 | 应对 |
| 五阶段 | 准备阶段 static 值 | 零值 |
| 双亲委派 | 委派方向 | 先父后子向上 |
| 加载器三层 | Bootstrap/Ext/App | 各管什么 |
| 好处 | 为什么安全 | 核心类不被篡改 |
真题基础1. 类加载的双亲委派模型,加载请求首先会?
真题中档2. 准备阶段 static int a = 10; 中 a 的值是?
真题中档3. 下列哪个不是类加载连接阶段的子步骤?
真题拔高4. 双亲委派模型的主要好处是?
⑧ 必背知识点卡
五阶段:加载→验证→准备→解析→初始化
准备:static 赋零值 不是写的初值
初始化:执行 static 块真赋值
三层:Bootstrap/Ext/App
双亲委派:先向上委派父加载 父不行自己来
好处:核心类防篡改、避免重复
破坏委派:重写 loadClass Tomcat/SPI
⑨ 应用输出:实现一个热部署类加载器
场景:框架要能不停机重新加载修改后的类。
① 原理:类由加载器唯一标识,换一个新的类加载器加载同名 class,就得到"新版本类"。
② 做法:自定义 ClassLoader,重写 findClass 从指定目录读 class 字节码。
③ 破坏委派:热部署要先自己加载,避免父加载器缓存旧类,重写 loadClass 打破双亲委派。
④ 卸载:旧加载器及其加载的类在无引用后被 GC。
⑤ 注意:两个类即使 class 字节码相同,被不同加载器加载也不相等。
口述思路合上书说:"热部署就是换新类加载器重写 loadClass,加载新版 class 旧的回收。"
⑩ 分层练习(基础 + 中档 + 拔高)
▍基础 6 题
基础1类加载过程五阶段?
加载、验证、准备、解析、初始化。
基础4三层加载器?
Bootstrap、Ext、App。
基础5初始化阶段做什么?
执行 static 代码和赋值。
基础6启动类加载器加载什么?
JRE 核心类 rt.jar。
▍中档 6 题
中档7static final 常量在准备还是初始化?
final 常量在准备阶段就赋值(ConstantValue)。
中档8为什么双亲委派安全?
核心类先被 Bootstrap 加载,用户伪造类无法替换。
中档9主动初始化时机?
new、静态方法、静态字段、反射、子类触发。
中档10自定义类加载器重写哪个方法?
遵守委派重写 findClass;破坏委派重写 loadClass。
中档11解析阶段做什么?
符号引用转直接引用(内存地址)。
中档12App 类加载器加载谁?
classpath 下的应用类。
▍拔高 6 题
拔高13Tomcat 为什么破坏双亲委派?
每个 Webapp 用独立加载器,实现应用间类隔离、热部署。
拔高14SPI (JDBC)怎么破坏委派?
核心类要加载 classpath 的实现类,用线程上下文类加载器反向委派。
拔高15类的唯一性由什么决定?
类加载器 + 全限定名,两者相同才算同一个类。
拔高16什么是隐式加载?
new 一个类时它引用的其他类被自动加载。
拔高17JIT 和类加载关系?
类加载后字节码进解释执行,热点代码 JIT 编译成本地码。
拔高18卸载类的条件?
该类所有实例被回收、加载器被回收、Class 对象无引用。
⑪ 记忆口诀 + 7 天复习计划
三句口诀① 加载验证准备解析初始化,准备零值初始化真赋值。② 双亲委派先问父,核心类安全不被篡。③ 三层 Bootstrap Ext App,热部署破坏委派。
| 天 | 任务 | 自检 |
| 第 1 天 | 读②③④,画五阶段 | 准备初始化分清 |
| 第 2 天 | 背三层加载器 + 基础 1-6 | 委派方向对 |
| 第 3 天 | 做中档 7-12,说委派过程 | 父加载顺序对 |
| 第 4 天 | 做拔高 13-18,理解 Tomcat | 能讲清破坏委派 |
| 第 5 天 | 做⑦真题 4 题 | 限时每题 2 分钟 |
| 第 6-7 天 | 合上书默写五阶段 | 不看资料全默对 |
← 返回软件技术总览