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

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.dtcms.com/a/290798.html

相关文章:

  • 二维DP深度解析
  • Linux(Centos 7.6)命令详解:jobs
  • 服务器后台崩溃的原因
  • openpnp - 贴片前,矫正板子位置时,使用多个mark点的位置并不一定精确(mark点可能板厂做的位置就不准)
  • 小智ai MCP学习笔记
  • 2021 RoboCom 世界机器人开发者大赛-本科组(复赛)解题报告 | 珂学家
  • SOLIDWORK教育版实时协作打破空间限制
  • 组合设计模式
  • 笔试——Day14
  • tcp的三次握手与四次挥手
  • 手机录制视频时,硬编码和软编码哪个质量高?(硬件编码、软件编码)
  • 跨端分栏布局:从手机到Pad的优雅切换
  • 删除 XML 格式中双引号内的空格
  • odoo-059 xml中字段上写 domain 和 filter_domain 什么区别
  • 对理性决策模型的剖析及应用路径
  • vue2使用v-viewer图片预览:打开页面自动预览,禁止关闭预览,解决在微信浏览器的页面点击事件老是触发预览初始化的问题
  • OpenEuler 22.03 系统上安装配置gitlab runner
  • Linux网络编程-osi、udp
  • nextjs+react接口会请求两次?
  • react class和function 如何模拟vue中的 双向绑定 监听 computed的方式
  • macbookpro m1 max本儿上速搭一个elasticsearch+kibana环境
  • Electron 主进程与渲染进程之间交互方式
  • Spring Boot自动装配原理深度解析:从核心注解到实现机制
  • Electron使用WebAssembly实现CRC-16 原理校验
  • YModem在Android上的实现(四)
  • 自动化测试概念和时机
  • Java -- 自定义异常--Wrapper类--String类
  • MySQL表的基础操作
  • 第三章自定义检视面板_创建自定义编辑器类_编扩展默认组件的显示面板(本章进度6/9)
  • 奥比中光深度相机开发