写点什么

Java 24 减少对象头的大小并节省内存

作者:Ben Evans

  • 2024-12-13
    北京
  • 本文字数:1756 字

    阅读完需:约 6 分钟

Java 24减少对象头的大小并节省内存

JEP450(Compact Object Headers,紧凑对象头)已经成为 JDK 24 的交付目标,并且已合并到了主版本中。


这个目前处于实验阶段的特性通过缩小 HotSpot 中强制对象头的大小来优化堆利用率。这应该会减少整体堆的大小,提高部署密度,并增加数据局部性。


当前的实现情况概述


HotSpot 将所有对象存储在 Java 堆中,Java 堆是进程的“C 堆”的连续区域。在 Java 中始终是通过引用来处理对象,例如:


  1. 引用对象的局部变量包含从 Java 方法的堆栈帧到 Java 堆的指针。

  2. 引用类型的对象字段从一个 Java 堆位置指向另一个位置。


Java 引用的目标地址始终是对象头的开始处(这在当前版本的 HotSpot 中是强制性的)。


每个对象上都有标头(数组还有一个额外的 32 位标头来存储数组的长度)。标记字是前 64 位,用于特定于实例的元数据,即支持以下特性:


  • 垃圾回收——存储对象的年龄(以及可能的转发指针)

  • 哈希码——存储对象的稳定身份哈希码

  • 锁——存储对象的锁 / 监视器


在某些情况下,标记字将被覆盖并被替换为指向更复杂数据结构的指针。这会使紧凑对象头的实现稍微复杂一些。


在标记字之后是类(或 klass)字,用于计算指向此类类型的每个对象所共享的元数据的指针。这用于方法调用、反射、类型检查等。


klass 元数据(或 klass)保存在元空间中,元空间位于 Java 堆之外,但在 JVM 进程的 C 堆之内。由于它们存在于 Java 堆外,因此 klass 不需要 Java 对象头,而且它们与反射中使用的类对象(真正的 Java 对象)不同。


klass 字最初是标头的一个完整机器字,但这在 64 位的架构上是很浪费的,因此引入了一种称为“压缩类指针”的技术。这将类指针编码为 32 位(通过使用缩放和偏移方法),适用于加载小于 4GB 类文件的任何应用程序。


因此,除了极端情况外,64 位版本的 HotSpot 上的非数组对象要支付 96 位的“标头税”。相比之下,这是轻量级的:直到最近,Python 的标头税还是 308 字节,但 JEP 450 的目的是为了做得更好,将标头的总大小减少到 64 位。


引入紧凑对象头


这个新实现是作为 OpenJDK 的“Project Lilliput”的一部分开发的,它减少了两个目标 64 位平台(x64 和 AArch64)上的对象头大小。


总体目标是:


  • 将目标平台上的吞吐量和延迟开销限制在 5% 内,并且只有在极少数情况下才能达到这一限制

  • 不会在非目标平台上引入可测量到的吞吐量或延迟开销


事实上,目前的测试只显示了极少数的回归(JDK 24 正在对它们进行修复)。到目前为止,亚马逊(Amazon)的测试表明,许多工作负载实际上在吞吐量方面受益,有时甚至会有大幅提升——一些工作负载的 CPU 利用率下降了 30%。


该项目试图利用观察到的事实,即许多 Java 工作负载的平均对象大小较小,只有 32 到 64 字节。这相当于约 20% 的标头税。因此,即使对象头大小略有改进,也可以显著减少堆的占用空间。反过来,这可以提高数据局部性并减少 GC 压力,从而带来进一步的潜在性能优势。


为了实现这种标头的减小,标记字和类字被组合成一个 64 位字,布局如下:



我们应该注意到以下几个方面:


  1. 现在有 22 位(而不是 32 位)用于标识对象类类型。这意味着我们可以加载到 JVM 进程中的不同类类型的数量约为 400 万个。

  2. 哈希码的大小不会变。

  3. 锁定操作不再覆盖标记字。这将保留压缩的类指针。

  4. 为了保持对压缩类指针的直接访问,GC 转发操作变得更加复杂。

  5. 有 4 个未使用的位保留用于未来的增强(例如 Valhalla 项目)


如果 Java 锁存在争用,那么新的实现需要查找保存锁信息的 辅助数据结 构的地址。这种方法称为“对象监视表”,已经在 JDK 22 中实现了,并由默认启用的新开关 UseObjectMonitorTable 激活。紧凑对象头依赖于此机制。


如果没有发现任何阻碍问题,这一特性将作为 JDK 24 的一部分发布(最初是一个实验特性),发布时间预计在 2025 年 3 月。长期的目标是使该机制成为受支持平台上唯一的标头表示,但这可能需要更多的版本。它还取决于对实际工作负载的广泛测试,目前缺乏性能和其他回归。甚至还有正在进行的探索性工作,以查看是否有可能将标头大小减小到 32 位。


一旦该特性在 JDK 24(测试版或最终版)中可用,应用程序团队可以通过命令行开关 -XX:UseCompactObjectHeaders 来激活该新特性以测试他们的工作负载,并寻找与之相关的性能差异,从而为长期目标提供帮助。


原文链接:

https://www.infoq.com/news/2024/11/compact-headers-java24/

2024-12-13 08:007021

评论

发布
暂无评论
发现更多内容

React源码分析7-state计算流程和优先级

flyzz177

React

一次关于 MySQL 主从模式采用 GTID 的实践记录

风铃架构日知录

Java MySQL IT 主从复制 MySQL 数据库

React源码分析6-hooks源码

flyzz177

React

一次JVM GC长暂停的排查过程

京东科技开发者

Java 后端 JVM 虚拟机 企业号 1 月 PK 榜

微服务的版本号要怎么设计?

江南一点雨

微服务 语义化

《金融电子化》:隐私计算赋能银行助贷业务自主风控 | 华夏银行×洞见科技

洞见科技

隐私计算 风控

视频实时自然美颜, 无惧素颜上镜

HarmonyOS SDK

HMS Core

Jenkins 构建过程中提示 GPG 错误

HoneyMoose

ClickHouse 挺快,esProc SPL 更快

陈橘又青

如何把 高并发限流 实现的那叫一个优雅!

风铃架构日知录

Java 程序员 高并发 IT 限流

ShardingSphere分库分表schema名称导致NPE问题排查记录

小小怪下士

Java 程序员 后端

带你认识数仓的增量备份核心设计

华为云开发者联盟

数据库 后端 华为云 数仓 企业号 1 月 PK 榜

Git操作不规范,战友提刀来相见!

王中阳Go

golang git 深度思考 高效工作 学习方法

信用卡APP评测系列:科技赋能信用卡APP创新升级,助力客户体验提升

易观分析

金融 信用卡

LogicFlow安装与准备工作

小鑫同学

前端 vite Vue 3 Vue3 Typescript

Postgresql分析慢sql

查拉图斯特拉说

数据库 postgresql db PgSQL PG库

Jenkins 项目的 gpg: signing failed: Bad passphrase 错误

HoneyMoose

公共服务 智慧政务数据可视化大屏一体化系统

2D3D前端可视化开发

数据可视化 数字政务 智慧政务 数字政府 可视化大屏

Java高手速成 | 高质量代码编写最佳实践

TiAmo

编程好习惯 设计原则 Java’

赞赞赞!融云收获行业媒体「组团打 Call」

融云 RongCloud

React源码分析5-commit

flyzz177

React

Serverless 奇点已来,下一个十年将驶向何方?

Serverless Devs

为什么网络I/O会被阻塞

华为云开发者联盟

后端 开发 华为云 企业号 1 月 PK 榜

关于 Serverless 应用架构对企业价值的一些思考

Serverless Devs

云图说 | Workflow:流水线工具,助您高效完成AI开发

华为云开发者联盟

人工智能 华为云 AI开发 企业号 1 月 PK 榜

二维码的秘密

古时的风筝

二维码 二维码生成

甩掉容量规划炸弹:用 AHPA 实现 Kubernetes 智能弹性伸缩

阿里巴巴中间件

阿里云 Kubernetes 云原生 AHPA

ISV生态合作伙伴体系多领域赋能,开拓市场赛道

元年技术洞察

数据中台 数据 数字化转型 ISV 方舟平台

行业分析| 交通综合执法对讲系统

anyRTC开发者

指挥调度 快对讲 语音对讲 视频对讲 综合执法

一个词语总结2022,你的是什么? | 2022 年度总结

陈言必行

2022年终总结

重磅发布丨从云原生到 Serverless,先行一步看见更大的技术想象力

Serverless Devs

Java 24减少对象头的大小并节省内存_编程语言_InfoQ精选文章