← [ BACK_TO_NOTES ]

JVM 类加载与字节码概览

类如何被加载、链接与初始化,以及字节码作为执行中间表示的边界(规范 vs 实现)。

#concept #growing #dev #java

[!info] related notes

JVM 类加载与字节码概览

这个概念为什么出现

ClassNotFoundException、NoClassDefFoundError、版本不匹配、SPI 与热加载问题,最终都落到类如何进入 JVM。字节码是编译产物的可验证中间表示。

[!abstract] 一句话理解 类加载大致经历加载→链接(验证/准备/解析)→初始化;字节码由类文件承载,JVM 解释/JIT 执行;不同加载器形成命名空间。

最小可观察示例

场景:确认应用类由哪个加载器装入

public class LoaderPeek {
    public static void main(String[] args) {
        ClassLoader cl = LoaderPeek.class.getClassLoader();
        System.out.println(cl);
        System.out.println(String.class.getClassLoader()); // 引导加载器,在本示例使用的 HotSpot 中表示为 null
    }
}
javac LoaderPeek.java && java LoaderPeek

在普通 HotSpot 命令行运行中:第一行是应用类加载器描述(具体名称和标识不固定),第二行是 null。null 表示引导加载器,不是平台加载器。

结合场景再看三个关注点

  1. 非数组类身份 = 二进制名称 + 定义它的加载器;发起加载请求的加载器可能只是委托方。
  2. 初始化触发点(首次主动使用)影响 static 副作用。
  3. 字节码版本与运行 JDK 要兼容。

核心概念与准确模型

1. 加载器层级(经典模型,模块时代有演进)

  • 引导 / 平台 / 应用
  • ClassLoader.loadClass 默认先委托父加载器;自定义加载器可以改变委托策略。核心类还受到平台的加载限制,不能把默认委托当成所有加载器的强制规则。

2. 链接与初始化

  • 验证字节码安全
  • 准备阶段为静态字段分配存储并设置默认值;常量字段另有规范规定,普通字段初始化器与 static 块在初始化阶段执行。
  • 解析可延后到符号引用首次使用,不能把整条加载链路理解为必然一次完成。
  • 初始化执行类初始化逻辑(若存在则为 <clinit>);读取编译期常量、获取类字面量或创建该类的数组本身,不触发该类初始化。

3. 字节码

  • javap -c 观察
  • 操作数栈与局部变量表模型

边界情况与反直觉行为

  1. 显式按名加载失败可抛 ClassNotFoundException;运行时需要的类无法定义/加载,或类先前初始化失败后的再次使用,可导致 NoClassDefFoundError。非 Error 异常导致初始化失败时,首次通常表现为 ExceptionInInitializerError。
  2. 循环初始化可能看到默认值。
  3. 容器/插件多加载器极易“同名类转换失败”。

常见误区

[!warning] 常见误区:以为类只加载一次全局唯一 不同加载器可加载同名类为不同运行时类。

工程实践

  1. 依赖冲突用 jdeps/构建 tree 先查。
  2. 框架 SPI 注意 ServiceLoader 与 TCCL。
  3. 生产开启类加载相关诊断要克制开销。
  4. 读 JVMS 章节时区分必须 vs 实现。

本节总结

  • 加载链路解释大量“找不到类”
  • 加载器命名空间
  • 字节码是可验证 IR

自测题

  1. 为什么容器里 ClassCastException 可能“看起来类型一样”?
  2. static 初始化何时跑?
参考答案
  1. 同一二进制名称由不同加载器分别定义,运行时类型不同;仅由不同加载器发起请求但最终委托给同一定义加载器则不会。
  2. 类型首次主动使用触发初始化(规范定义的触发条件)。

延伸阅读与资料来源

资料类型支撑内容
JVMS Class Loading规范加载与链接
javap tool工具反汇编
创建于 2026/7/15 更新于 2026/10/6
Digital Biome
Access

键盘导航

j / k / ↑ / ↓
选择对象
Enter / o
打开选择
/ 或 Ctrl+K
全站搜索
i / f / 1–4
筛选当前列表
g → h / l / p / t / a
首页 / 笔记 / 项目 / 工具 / About
r → 1–9
打开所选对象的关联
u
返回上一页
Esc
关闭浮层 / 取消命令;输入框内清空文本