← 返回软件技术总览 软件技术 · 知识点深化 · 类加载机制:双亲委派、加载-连接-初始化
知识点深化 · JVM · 类加载

类加载机制:双亲委派、加载-连接-初始化

一个 .class 文件到能被运行,要经过加载→验证→准备→解析→初始化。类加载器用双亲委派机制:先让父加载器尝试,自己实在加载不了才上。这一页把生命周期五阶段和双亲委派讲透。

① 小白第一课怎么学(4 步走,约 60 分钟)

别急着背代码,先按这四步建立直觉:

1看图建立直觉(10 分钟)
读②③:class 文件如何被 JVM 吃下。
2记五阶段(15 分钟)
读④:加载连接初始化。
3手推委派(20 分钟)
精读⑤。
4刷题纠错(15 分钟)
做⑦⑩,错题回⑥。
本课小目标学完你要能:① 说出类加载五阶段;② 解释双亲委派流程和好处;③ 说出自定义类加载器时机。

② 一图看懂:类加载全地图

类加载 加载 读 class 成二进制 连接 验证/准备/解析 初始化 执行 static 块/赋值 双亲委派 先父后子,安全 应用:热部署/容器隔离 破坏委派:SPI/Tomcat 易错:准备≠初始化 准备零值,初始化才赋真
读法:中心是类加载,左生命周期阶段右委派机制,下是应用与易错。

③ 本质直觉:class 文件从磁盘到 JVM 内存的五站旅程

加载:把 .class 字节码读进来,在堆里生成一个代表该类的 java.lang.Class 对象。

连接:① 验证——检查字节码合法;② 准备——给 static 变量分配内存并赋零值(不是你写的初始值);③ 解析——常量池符号引用转直接引用。

初始化:真正执行 static 代码块和 static 变量赋值。这是类加载的最后一步。

双亲委派:加载请求先委托给父加载器,父加载不了自己才加载。层层向上到启动类加载器。

双亲委派层级 启动类加载器 扩展类加载器 应用类加载器 自定义加载器 请求向上委派,成功向下返回
双亲委派的好处核心类(如 java.lang.String)永远被启动类加载器加载,用户写个假 String 也顶替不了——安全。同个类只加载一次,避免重复。

④ 完整体系与对比表

生命周期五阶段

阶段做什么
加载读 class 字节码,生成 Class 对象
验证检查字节码格式合法
准备static 变量分配内存,赋零值
解析符号引用→直接引用
初始化执行 static 块和赋值

三层类加载器

加载器加载什么
启动类加载器 BootstrapJRE/lib 核心类(rt.jar)
扩展类加载器 ExtensionJRE/lib/ext 扩展类
应用类加载器 Applicationclasspath 下用户类

⑤ 用法场景与典型例题

例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类加载过程五阶段?
加载、验证、准备、解析、初始化。
基础2准备阶段 static 赋什么?
零值。
基础3双亲委派先找谁?
父加载器。
基础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 天合上书默写五阶段不看资料全默对

← 返回软件技术总览