news 2026/5/26 23:59:27

【JVM】类初始化和加载

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【JVM】类初始化和加载

一、对象的创建过程

1. 类加载检查

当尝试创建一个对象时,JVM首先会到元空间中查找该对象的类符号引用(可以理解为类的模板信息)。检查这个类是否已经被加载、解析和初始化。如果没有,则会触发完整的类加载过程

2. 分配内存

类加载检查通过后,JVM会在堆内存中为新对象划分一块内存空间。具体的内存分配方式取决于垃圾收集器的实现,常见的有:

  • 指针碰撞:适用于内存规整的GC算法(如Serial、ParNew)
  • 空闲列表:适用于内存不规整的GC算法(如CMS)
3. 初始化零值

内存分配完成后,JVM会将对象的所有实例字段初始化为对应类型的零值

  • 数值类型(int、long等):0
  • 布尔类型:false
  • 引用类型:null

此操作确保了对象字段在使用前都有确定的初始值,这是Java内存安全的重要保障。

4. 设置对象头

接下来设置对象的对象头(Object Header),主要包括:

  • Mark Word:存储对象的运行时数据
    • 哈希码(HashCode)
    • GC分代年龄
    • 锁状态标志
    • 线程持有的锁等
  • Klass Pointer:指向方法区中的Class对象,确定对象的类型
  • 如果是数组对象,还会包含数组长度信息
5. 执行init方法

上述步骤完成后,从JVM角度看一个对象已经创建完毕。接着执行实例初始化

  1. 初始化字段:按照代码顺序执行字段的显式初始化
  2. 执行实例代码块:编译器会将所有非静态代码块收集并插入到构造器开头
  3. 执行构造器代码:执行开发者编写的构造函数代码

至此,一个完整的、可用的Java对象才真正创建完成。


阶段执行内容涉及内存区域
类加载检查查找类符号引用,必要时加载类元空间
分配内存在堆中划分对象空间
初始化零值设置字段默认值(0、false、null)
设置对象头设置对象元数据(Mark Word、类型指针)
执行init方法执行代码块和构造器,完成对象初始化

二、类加载过程

类加载是JVM将类的字节码文件加载到内存,并进行验证、准备、解析和初始化的完整过程。整个过程分为三大阶段:加载 → 链接 → 初始化,其中链接阶段又包含验证、准备、解析三个子阶段。

1. 加载(Loading)

核心任务:将类的字节码数据加载到内存中,并创建对应的Class对象。

具体过程

  • 读取字节码:通过类的全限定名获取对应的字节码文件(.class
  • 二进制转换:将字节码转换为方法区中的运行时数据结构
  • 创建Class对象:在中生成一个代表该类的java.lang.Class对象
  • 建立访问入口:Class对象作为程序访问方法区中类元数据的入口
2. 链接(Linking)

链接阶段负责将加载到内存的类数据进行整合和准备。

2.1 验证(Verification)

确保被加载的类符合JVM规范,不会危害虚拟机安全。

四个验证阶段

验证阶段验证内容重要性
文件格式验证魔数、版本号、常量池等确保.class文件格式正确
元数据验证类的继承关系、字段/方法访问性确保语义符合Java规范
字节码验证方法体、栈帧、类型转换等确保程序逻辑正确性
符号引用验证符号引用的合法性确保解析能正常进行
2.2 准备(Preparation)

为类的静态变量分配内存并设置初始值。

关键规则

// 情况1:普通static变量(赋默认值)publicstaticintcount;// 准备阶段:count = 0publicstaticStringname;// 准备阶段:name = null// 情况2:static final编译时常量(直接赋实际值)publicstaticfinalintMAX=100;// 准备阶段:MAX = 100publicstaticfinalStringTITLE="App";// 准备阶段:TITLE = "App"引用// 情况3:static final非编译时常量(赋默认值)publicstaticfinalDateNOW=newDate();// 准备阶段:NOW = null

内存分配

  • 静态变量在方法区(元空间)分配内存
  • 基本类型分配固定大小,引用类型分配引用空间
2.3 解析(Resolution)

将常量池中的符号引用替换为直接引用

引用类型符号引用(解析前)直接引用(解析后)
类/接口java/lang/StringClass对象内存地址
字段java/lang/System.out字段内存偏移量
方法java/io/PrintStream.println方法入口地址或方法表索引

解析时机

  • 积极解析:类加载时就解析所有符号引用(默认)
  • 惰性解析:第一次使用时才解析(某些JVM实现)
3. 初始化(Initialization)

类加载的最后阶段,执行类的初始化代码。

触发时机(以下情况之一):

  1. 创建类的实例(new
  2. 访问类的静态变量(非final)
  3. 调用类的静态方法
  4. 使用反射(Class.forName()
  5. 初始化子类时,父类未初始化
  6. JVM启动时指定的主类

执行内容:执行<clinit>()方法(类构造器)

publicclassExample{// 静态变量赋值(收集到<clinit>())publicstaticinta=initA();// 静态代码块(收集到<clinit>())static{System.out.println("静态代码块");}privatestaticintinitA(){return100;}// <clinit>()方法包含:// 1. a = initA()// 2. System.out.println("静态代码块")}

初始化顺序

  1. 父类静态变量和静态代码块
  2. 子类静态变量和静态代码块
  3. 父类实例变量和实例代码块
  4. 父类构造器
  5. 子类实例变量和实例代码块
  6. 子类构造器
4. 使用(Using)

类完成加载后进入使用阶段,程序可以:

  • 创建类的实例对象
  • 访问类的静态成员
  • 调用类的方法
  • 使用反射操作类
5. 卸载(Unloading)

当类不再被需要时,JVM会将其从内存中卸载。

卸载条件(同时满足):

  1. 实例全部回收:该类所有的实例都已被垃圾回收
  2. ClassLoader回收:加载该类的ClassLoader已被回收
  3. Class对象无引用:该类的Class对象没有被任何地方引用

卸载过程

// 假设场景:Web应用卸载WebappClassLoaderloader=newWebappClassLoader();Class<?>clazz=loader.loadClass("com.example.MyServlet");// 当Web应用停止时:// 1. 销毁所有MyServlet实例 → 实例回收 ✓// 2. 回收WebappClassLoader → ClassLoader回收 ✓// 3. 清除对Class对象的引用 → 无引用 ✓// 结果:MyServlet类被卸载

注意事项

  1. 启动类加载器加载的类通常不会被卸载
  2. 自定义类加载器加载的类在适当条件下可被卸载
  3. 类的卸载有助于减少元空间内存占用

📌 完整类加载流程图

开始 ↓ [加载阶段] ├── 读取.class文件 ├── 转换运行时结构 ├── 创建Class对象 └── 建立方法区访问入口 ↓ [链接阶段] ├── [验证] │ ├── 文件格式验证 │ ├── 元数据验证 │ ├── 字节码验证 │ └── 符号引用验证 │ ├── [准备] │ ├── 分配静态变量内存 │ ├── 设置默认值/实际值 │ └── 处理static final常量 │ └── [解析] ├── 类/接口解析 ├── 字段解析 └── 方法解析 ↓ [初始化阶段] ├── 执行<clinit>()方法 ├── 初始化静态变量 └── 执行静态代码块 ↓ [使用阶段] ├── 创建实例 ├── 访问成员 └── 调用方法 ↓ [卸载阶段](条件满足时) ├── 回收所有实例 ├── 回收ClassLoader └── 清除Class引用 ↓ 结束

关键要点总结

  1. 类加载是懒加载的:只有真正使用时才会触发初始化
  2. 准备阶段只处理静态变量:实例变量在对象创建时初始化
  3. 解析将符号变直接:从描述性引用到具体内存地址
  4. 初始化执行clinit():收集所有静态初始化代码
  5. 卸载条件苛刻:需要实例、ClassLoader、Class对象都符合条件
  6. 双亲委派保护核心:防止核心类被篡改,确保类唯一性
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/23 10:03:34

PHP构建智能家居温控中心(从零到上线全流程)

第一章&#xff1a;PHP构建智能家居温控中心概述在物联网快速发展的背景下&#xff0c;智能家居系统逐渐成为现代家庭的重要组成部分。其中&#xff0c;温度控制作为环境调节的核心功能之一&#xff0c;直接影响居住的舒适性与能源效率。利用PHP这一广泛应用于Web开发的服务器端…

作者头像 李华
网站建设 2026/5/21 3:57:01

要实现“新建需求”功能

要实现“新建需求”功能&#xff0c;我们可以基于 Vue&#xff08;Element UI&#xff09; Spring Boot&#xff08;若依框架&#xff09; 做前后端分离开发&#xff0c;以下是完整实现方案&#xff1a; 一、后端&#xff08;Spring Boot 若依&#xff09; 1. 数据库表设计 需…

作者头像 李华
网站建设 2026/5/10 17:39:50

通俗理解卷积核与特征图

引言 在当今的科技世界中&#xff0c;人工智能&#xff08;AI&#xff09;已经渗透到我们生活的方方面面&#xff0c;尤其是图像识别、自动驾驶和医疗诊断等领域。其中&#xff0c;卷积神经网络&#xff08;Convolutional Neural Network&#xff0c;简称CNN&#xff09;是深度…

作者头像 李华
网站建设 2026/5/11 7:48:34

中兴通讯基站维护培训:HeyGem生成工程师教学视频

中兴通讯基站维护培训&#xff1a;HeyGem生成工程师教学视频 在通信网络日益复杂的今天&#xff0c;5G基站的部署密度持续攀升&#xff0c;设备迭代周期不断缩短。一线维护人员面临一个现实难题&#xff1a;如何在最短时间内掌握最新的故障处理流程&#xff1f;传统的培训方式—…

作者头像 李华
网站建设 2026/5/22 21:41:10

社会实践报告还在“记流水账”?百考通AI平台3分钟生成有深度、有反思、有社会价值的高质量总结

暑期结束&#xff0c;面对学校要求的社会实践报告&#xff0c;你是否还在苦恼于内容空洞、结构松散、写来写去只有“第一天走访社区&#xff0c;第二天发放问卷&#xff0c;第三天整理材料”这类流水账式记录&#xff1f;看似条理清晰&#xff0c;实则缺乏问题意识、没有理论联…

作者头像 李华
网站建设 2026/5/1 17:49:00

课程设计报告写成“操作手册”?百考通AI平台3分钟生成有原理、有分析、有工程思维的高质量总结

课程设计是工科、经管、教育等专业教学中的关键实践环节&#xff0c;但很多同学交出的报告却像一份“操作步骤清单”——“第一步打开软件&#xff0c;第二步输入参数&#xff0c;第三步点击运行……”缺乏理论支撑、过程反思与结果分析&#xff0c;被导师批为“只有流程&#…

作者头像 李华