当前位置: 首页 > ai >正文

JVM 类加载过程笔记

一、概述

JVM(Java Virtual Machine)在运行 Java 程序时,需要将 .class 字节码文件加载到内存中,并转换成可以被 JVM 执行的数据结构,这一过程就是 类加载过程(Class Loading Process)

JVM 的类加载机制具备高度灵活性与可扩展性,支持自定义类加载器,且类的生命周期分为以下几个阶段:

二、类的生命周期阶段

  1. 加载(Loading)
  2. 验证(Verification)
  3. 准备(Preparation)
  4. 解析(Resolution)
  5. 初始化(Initialization)
  6. (可选)使用(Using)
  7. (可选)卸载(Unloading)

前五个阶段属于 类加载的过程,使用和卸载属于类的生命周期的后期阶段。


三、类加载的五个阶段详解

1. 加载(Loading)

作用:
.class 文件的字节码从磁盘或网络加载到 JVM 内存中,并生成一个 Class 对象。

步骤:

  • 通过类的全限定名查找 .class 文件。
  • 读取字节流。
  • 将字节流转换成内存中的数据结构。
  • 创建 java.lang.Class 类的实例。

说明:

  • 使用 类加载器(ClassLoader) 完成。
  • 可以自定义类加载器实现特殊的加载逻辑。

2. 验证(Verification)

作用:
确保字节码文件的正确性与安全性,不会破坏 JVM 的稳定性。

主要检查:

  • 文件格式验证(魔数、版本号等)
  • 元数据验证(类结构正确性)
  • 字节码验证(操作码合法性、栈操作正确性)
  • 符号引用验证(类和方法是否存在)

3. 准备(Preparation)

作用:
为类的 静态变量 分配内存,并初始化默认值(不包括静态代码块和显式赋值)。

特点:

  • 所有静态变量初始化为零值(数值为0,对象为null,boolean为false)。
  • 不执行任何 Java 代码。
  • 这一步只是内存分配与默认值初始化。

示例:

public class Demo {static int a = 10;
}

在准备阶段,a 的值是 0,真正赋值为 10 的过程发生在 初始化阶段


4. 解析(Resolution)

作用:
将常量池中的 符号引用 转换为 直接引用

解析内容:

  • 类或接口的符号引用 → 直接引用
  • 字段符号引用 → 直接引用
  • 方法符号引用 → 直接引用
  • 接口方法引用 → 直接引用

说明:

  • 并非必须立即解析,可在运行时动态解析(延迟解析)。
  • 也可由 JVM 实现决定是否在加载时解析。

5. 初始化(Initialization)

作用:
执行类构造器 <clinit>() 方法,对静态变量进行显式赋值和执行静态代码块。

执行条件:

  • 创建类的实例
  • 访问类的静态变量或静态方法
  • 反射调用 Class.forName()
  • 初始化类的子类时,其父类会被先初始化
  • JVM 启动时指定的主类(含 main 方法)

注意:

  • 每个类只会初始化一次。
  • 父类先于子类初始化。

四、类加载器(ClassLoader)

类加载器的类型

名称说明
Bootstrap ClassLoader(启动类加载器)加载 java.* 核心类库(由 C++ 实现,非 Java 类)
Extension ClassLoader(扩展类加载器)加载 ext 目录下的类(如 jre/lib/ext
Application ClassLoader(系统类加载器)加载应用类路径(classpath)下的类
自定义类加载器用户可以继承 ClassLoader 实现自己的加载逻辑

双亲委派模型(Parent Delegation Model)

工作流程:

  1. 当前类加载器收到加载请求。
  2. 委派给父类加载器。
  3. 父类加载器继续向上委托,直到 Bootstrap ClassLoader。
  4. 若父加载器无法加载,再由当前加载器尝试加载。

优点:

  • 避免类的重复加载。
  • 保证核心类安全性(如 java.lang.String 永远由启动类加载器加载)。

五、类的卸载(Unloading)

条件:

  • 该类的 Class 对象没有任何引用。
  • 加载该类的类加载器没有任何引用。
  • JVM 才能卸载该类。

说明:

  • 卸载的前提是类加载器无引用,通常发生在动态部署的模块或插件系统中。
  • 主动卸载需要结合自定义类加载器。

六、类加载过程图解

              ┌────────────┐│ .class 文件 │└────┬───────┘↓┌────────────┐│ 加载 Loading│└────┬───────┘↓┌───────────────────┐│ 验证 Verification │└────┬──────────────┘↓┌────────────────┐│ 准备 Preparation│└────┬───────────┘↓┌──────────────┐│ 解析 Resolution│└────┬─────────┘↓┌─────────────────────┐│ 初始化 Initialization│└─────────────────────┘
http://www.xdnf.cn/news/15897.html

相关文章:

  • leetcode-sql-627变更性别
  • 计算机发展史:互联网时代的万物互联与全球变革
  • stm32mp157f-dk2安装镜像并且部署qt全流程
  • tcp的三次握手与四次挥手
  • Softhub软件下载站实战开发(二十):Docker部署全攻略
  • WPF——自定义ListBox
  • 注解 + AOP 的方式记录日志到 t_ops_sync_log 表
  • 使用相机不同曝光时间测试灯光闪烁频率及Ai解释
  • 宝塔访问lnmp项目,跳转不到项目根目录问题解决
  • 后训练(Post-training)语言模型
  • Linux system-timesyncd时间同步机制详解
  • Django模板系统
  • Oracle 数据库共享池与大池调优指南
  • RuoYi配置多数据源失效
  • 【烧脑算法】拓扑排序:从“依赖”到“序列”,理解题目中的先后逻辑
  • 虚拟电厂蓄势:源网荷储联动如何实现电力系统的 “智慧蝶变”?
  • 如何升级到macOS Tahoe:全面指南与实用步骤
  • 从一开始的网络攻防(六):php反序列化
  • 关于JavaWeb的总结笔记
  • 云原生周刊:K8s 中的后量子密码学
  • 【学习路线】C#企业级开发之路:从基础语法到云原生应用
  • docker 容器学习
  • zabbix企业级分布式监控环境部署
  • 【Prometheus+Grafana篇】监控通过Keepalived实现的MySQL HA高可用架构
  • 在翻译语义相似度和会议摘要相似度评估任务中 ,分类任务 回归任务 生成任务区别
  • 布局AI +文化新赛道,浙江省文化产业投资集团赴景联文科技调研交流
  • uniapp【uni-ui】【vue3】样式覆盖方式记录
  • Git上传与下载GitHub仓库
  • Neo4j 5.x版本的导出与导入数据库
  • 【系统全面】Linux内核原理——基础知识介绍