2.1 JVM对象创建

对象创建

本文基于 Hotspot 虚拟机,其他 JVM 行为可能会有区别

本文中的 Eden 区泛指各 GC 中新对象的分配区域,如 G1 的 Eden Region、ZGC 的分配 Page 等

本文行为均基于默认行为,某些 JVM 参数会导致行为不同

对象创建大致可以分为如下几个步骤

复制代码
元数据检查 -> 内存分配 -> 设置对象头 -> 对象内容初始化

详解

通过 new 指令方式创建类实例的流程图如下所示
内存分配



充足
不足

剩余空间小于浪费阈值
剩余空间大于浪费阈值
遇到 new 指令
类元数据已存在?
执行类加载

Loading - Linking - Init
启用 TLAB?
TLAB 余额充足?
TLAB 内分配

无锁指针碰撞
对象大小

vs TLAB剩余空间?
CAS 竞争申请新 TLAB

然后分配
CAS 竞争堆内存

直接分配
空间清零

TLAB预清零 / 分配后清零
设置对象头

MarkWord + KlassPtr
new 指令完成

对象引用入栈
继续执行字节码
invokespecial

触发构造方法
对象真正可用

元数据检查

检查当前命令能否在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否被加载解析和初始化过,如果没有的话会先进行类加载过程。

在元数据中会拿到对象所需内存的大小

内存分配

堆内存格局和 gc 强相关,此处尽量不涉及具体的内存格局细节

堆不是线程独占内存,同时内部对象会频繁的被 gc 清理,因此内存分配大致来说有两个问题,一是分配到哪块内存,二是怎么保证分配的并发安全

指针碰撞

在绝大部分 gc 中,Eden 区都是一块至少局部规整的内存。换句话说有某个地址作为分界点,使用过的内存在一边,空闲的内存在另一边。那么分配内存就只是把分界地址的指针往空闲方向挪动一段与对象所需内存大小相等的距离,这种分配方式就是指针碰撞。

空闲列表

CMS 是非压缩 GC,无法保证堆局部规整,需要维护一个列表记录内存的占用情况来辅助分配对象,这种分配方式就是空闲列表(实际上还是有机制保证局部规整的,但是 CMS 都废弃了就不深入了)

CAS

简单来说就是通过硬件的 CAS 原子操作与自旋实现并发安全,下图是碰撞指针的 CAS 分配示例
CAS 原子操作
准备工作


利用最新 Top

直接重算
开始分配
读取/更新快照

snapshot = 当前 Top
计算期望新指针

new_top = snapshot + size
比较:

内存 Top == snapshot ?
匹配:

Top 更新为 new_top
不匹配:

Top 未修改

获取最新 Top
分配成功

返回 snapshot 地址

TLAB

TLAB(Thread Local Allocation Buffer),简单来说就是给线程预分配一块内存,当新对象可以直接放到 TLAB 中时就可以直接无锁分配。

TLAB 本身的内存申请也是通过 CAS 实现的。

空间清零

Java 语言规范规定的所有字段在未赋值前,必须有默认值,因此对象字段区域需要进行清零操作

这个步骤在流程图上标记在了设置对象头之前,但是实际上不同分配方式该步骤执行时机不同

  1. 堆上直接分配:同步清零
  2. TLAB 分配:TLAB 申请时批量清零整个 TLAB 块

设置对象头

设置对象的元数据

做完这个步骤后在 vm 层面对象就创建完了,只是对象内容还没有进行初始化

对象内容初始化

执行 <init>() 方法初始化对象内容

其他创建方式

除了标准构造(new 或者 反射)外,其他构造方式(克隆、反序列化、Unsafe)流程在在 vm 层面流程极其类似(clone略特殊,他分配内存时不进行空间清零步骤而是直接拷贝内存),只是对象内容初始化方式不同

创建方式 字节码/API 是否调用 <init> 内存初始化方式 内容初始化方式 备注
new 关键字 new 清零 构造方法 最标准的创建方式
反射 Class.newInstance Constructor.newInstance 清零 构造方法 最终调用 new 流程,但在 JVM 层面有安全检查开销
克隆 clone() 内存复制 - 内存初始化完内容也就初始化完了
反序列化 ObjectInputStream.readObject 视情况 清零 序列化流 通常调用第一个不可序列化父类的无参构造
Unsafe Unsafe.allocateInstance 清零 -
相关推荐
维天说1 小时前
CLI-Switch 2026年3月版历史设计:Hook、TTY 隔离与 JSON 状态
java·服务器·json
Zane19942 小时前
并发 vs 并行:别再傻傻分不清了,一文讲透 Java 并发编程的第一课
java·后端
噢,我明白了2 小时前
java中Excel的导入和导出(EasyExcel)
java·开发语言·excel
吠品2 小时前
Zabbix Web界面误报Server未运行的排查与解决
java·服务器·数据库
啊湘2 小时前
天气查询API接口 按月Token鉴权 实时天气 物联网可用 文档齐全
java·后端·struts
Java内核笔记3 小时前
告别十亿美元的错误 : Spring Boot 4 空安全 (JSpecify) 实战
java·spring boot·后端
糖果店的幽灵3 小时前
langgraph的 MessagesState 解读
java·开发语言·人工智能·windows·langgraph
极光代码工作室4 小时前
基于SpringBoot的在线博客系统
java·springboot·web开发·后端开发
我是唐青枫5 小时前
Java Spring Security 实战详解:从登录认证到 JWT 权限控制
java·spring
ihuyigui5 小时前
海外签收通知短信接口
android·java·开发语言·前端·数据库·后端