Java基础、中级、高级、架构面试资料

JVM 再瘦身,JDK 27 对象头公摊面积暴降 33%,CPU 降 30%

JAVA herman 21浏览
公告:“业余草”微信公众号提供免费CSDN下载服务(只下Java资源),关注业余草微信公众号,添加作者微信:xttblog2,发送下载链接帮助你免费下载!
本博客日IP超过2000,PV 3000 左右,急需赞助商。
极客时间所有课程通过我的二维码购买后返现24元微信红包,请加博主新的微信号:xttblog2,之前的微信号好友位已满,备注:返现
受密码保护的文章请关注“业余草”公众号,回复关键字“0”获得密码
所有面试题(java、前端、数据库、springboot等)一网打尽,请关注文末小程序
视频教程免费领
【腾讯云】1核2G5M轻量应用服务器50元首年,高性价比,助您轻松上云

昨天,我看到有网友留言说他没找到 OpenJDK 的 25.0.3 版本,当时我身边没有电脑,所以没有立即回复他。

然后,在今天的某个空闲时间段,我访问了 openjdk.org,查看了其中的 OpenJDK Release 25.0.3 具体的版本信息,依然在列。

我想可能是他没找对位置吧。接着我又随时翻看了一下 JDK 27 的进度,发现 JDK 27 中,要引入 JEP 534: Compact Object Headers by Default 了。

看到这个特性,是不是有种很熟悉的感觉?

没错,就是我前两天写携程入坑的那个紧凑对象头节省内存跳坑里的那篇文章,这个特性要在 JDK 27 中,默认开启了,这对于 Java 或 JVM 内存优化来说,具有里程碑意义。

JDK 27 计划于 2026 年 9 月 14 日发布,JEP 534 是其中的一项看似“低调”却影响深远的特性,紧凑对象头即将成为默认行为。这意味着,从 JDK 27 开始,Java 应用的内存占用将自动降低,GC 压力将自动减轻,而这一切不需要修改一行业务代码

JEP 534 是什么?

JEP 534 的全称是 Compact Object Headers by Default,即将紧凑对象头设为 HotSpot JVM 的默认对象头布局

文章配图参见 https://mp.weixin.qq.com/s/Rrpv6Q95e5UP56oIbGOhMw

要知道,在 64 位架构上,传统 Java 对象头占用 96 bits(12 字节),由两部分组成。

  • Mark Word(64 bits):存储锁状态、GC 分代年龄、身份哈希码等
  • Class Pointer(32 bits):指向类的元数据(Compressed Class Pointers)

而 JEP 534 将这一布局压缩至 64 bits(8 字节),通过把类指针嵌入 Mark Word 的未使用位中,直接削减了 33% 的对象头开销

虽然,目前 JEP 534 的状态为 #Proposed to Target(已提议纳入),预计将在 2026 年 5 月 19 日完成评审。但从 JDK 27 官方特性列表来看,它已被列为三个“Proposed to Target”的 JEP 之一,几乎可以确定的会纳入到 JDK 27 中。

这个判断依据有 3 点,下面分别展开一下。

状态明确指向 JDK 27

根据 OpenJDK 官方页面,JEP 534 的 Release 字段明确标注为 27,且状态为 Proposed to Target(已提议纳入目标版本),这是进入 JDK 的倒数第二步。

经过了充分的渐进式验证

JEP 534 并非凭空出现,它经历了完整的“孵化 → 实验 → 正式 → 默认”四步走策略。

  • JDK 24(JEP 450):作为实验特性首次引入,需手动开启
  • JDK 25(JEP 519):升级为正式产品特性,但仍需 -XX:+UseCompactObjectHeaders 手动开启
  • JDK 27(JEP 534):设为默认,无需参数自动生效

这种渐进式策略是 OpenJDK 对核心 JVM 特性的一贯谨慎做法。

大厂生产环境已背书

  • Amazon:已将紧凑对象头回移植到 JDK 17 和 JDK 21,在数百个生产服务中运行,实测 CPU 降低最高达 30%
  • SAP:在其下游 OpenJDK 发行版 SapMachine 中已默认开启紧凑对象头,每日运行大量测试套件
  • Oracle:通过了完整的 JDK 测试套件验证

正是有其它国外大厂的背书,所以携程也开始了在生产环境灰度更新替换,这也导致了携程跳进了一个 bug 坑里,这里就不细表了,具体可以阅读我上周发布的文章《JDK 25 的 G1GC 存在静默数据损坏 Bug,携程踩坑》。

更何况,JEP 534 的 Motivation 章节明确写道,It is time to make compact object headers the default mode.,是时候让紧凑对象头成为默认模式了。

这个特性要解决什么问题?

说起来不怕笑话,其它的语言的一些程序员,总是会攻击或讽刺 Java 语言,说它是一个内存开销大户。

不得不说,这可能是 Java 历史上最大的一个黑标签之一。要知道现在的 Java 早已不是原来的“阿斗”了。

我不管怎么黑,都不影响 Java 的伟大!

Java 对象头的隐性税

Java 开发者都知道“一切皆对象”,但很少人意识到,每个对象都在为“头信息”支付沉重的内存税

在典型的 Java 应用中。

  • 对象头占堆内存的 20% 以上
  • 对于 32~64 字节的小对象,12 字节的头意味着 37.5% 的额外开销
  • 微服务、Spring Boot、JSON 解析、集合类密集等场景,对象数量动辄千万级,这部分开销被急剧放大

更隐蔽的问题是缓存局部性(Cache Locality),更大的对象意味着更少的对象能塞进 CPU L1/L2 缓存,导致更多的主内存访问,性能被“悄悄偷走”。

这也是为什么这个特性一经推出,就立即受到大厂的追捧并在生产环境使用的原因之一。因为它的的确确能减少不少硬性成本。

快递包裹的填充物

可以想象一下,或者类别想象,你买了 100 个手机壳,每个手机壳(对象数据)本身不大,但每个都用了一个大纸箱(对象头)包装。纸箱占了一半体积,运输成本(内存/CPU)自然就高了。JEP 534 做的就是“换小纸箱”。

如果大商家发的货多,那一年的成本减少,至少是十几万起步。

带来哪些好处?

综合社区里的反馈来看,有以下 4 点显著的好处或收益。

堆内存显著降低

测试场景收益
SPECjbb2015堆内存减少 22%
10M 个 Point 对象基准测试提交内存减少 30%,使用内存减少 12%

CPU 使用率下降

测试场景收益
SPECjbb2015CPU 时间减少 8%
Amazon 生产环境最高 30% CPU 降低
高并发 JSON 解析执行时间减少 10%

GC 压力减轻

  • SPECjbb2015 的 GC 次数减少 15%(G1 和 Parallel GC 均适用)
  • 更少的对象头意味着更少的堆扫描工作量,GC 停顿更短、更稳定

云原生部署密度提升

  • 容器内存需求降低 → 单机可部署更多实例
  • 冷启动更快(内存分配减少)
  • 直接转化为云成本节省

正如一些知名老外程序员所言,这些改进在成本敏感的环境中尤其有价值,因为内存效率能直接转化为运营节省

技术原理

这其中的 4 字节是怎么省出来的?

我们先来看一下传统对象头布局。

┌────────────────────────────────────────┬────────────────────┐
│           Mark Word (64 bits)          │ Class Pointer (32) │
│  锁状态 | GC 年龄 | 哈希码 | 其他元数据  │  指向类元数据地址    │
└────────────────────────────────────────┴────────────────────┘
           12 字节 (96 bits) 总计

再看一下紧凑对象头布局。

┌────────────────────────────────────────────────────────────┐
│                    合并后的 64-bit 头                      │
│  锁状态 | GC 年龄 | 哈希码(31bit) | 类指针(22bit) | 其他    │
└────────────────────────────────────────────────────────────┘
           8 字节 (64 bits) 总计

通过上面的对比就可以发现,这其中的核心技巧如下所示。

  1. 类指针压缩:从 32-bit 压缩到 22-bit,支持约 400 万个唯一类,远超任何真实应用需求
  2. 嵌入 Mark Word:将压缩后的类指针直接嵌入 Mark Word 的未使用位中,消除独立的 Class Pointer 字段
  3. 保留 31-bit 哈希码:为避免哈希碰撞影响大哈希表性能,身份哈希码仍保留 31 位

有人可能会说,这不会不影响到锁机制的兼容性?

答案是,不影响。因为 Project Lilliput 在 JDK 22 引入了 Object Monitor Tables 基础设施,解决了 64-bit 头无法存储完整锁指针的问题,确保同步语义不受影响。

对开发者意味着什么?

我们先来看一下用法方面。

在 JDK 27 之前(JDK 25/26),需要手动开启。

java -XX:+UseCompactObjectHeaders -jar app.jar

在 JDK 27 及之后,默认开启,无需任何操作。

如果因特殊原因需要回退到旧布局(例如某些依赖旧对象头布局的 JNI/Unsafe 代码),可以通过下面的参数显式关闭。

java -XX:-UseCompactObjectHeaders -jar app.jar

与此同时,超过 95% 的小企业,或者国内用户,很多特性非默认不会手动进行开启的。一方面是,对某些特性不熟等影响的;另一方面是,不少小企业的 JDK 从不升级;最后是,预期的收益并没有大厂来的明显。

接下来,我们看一下注意事项。

  • 不能与 -XX:-UseCompressedClassPointers 同时使用(该参数已废弃)
  • x64 上的 ZGC 支持仍在完善中(但 G1、Parallel、Shenandoah 已完全支持)
  • 类数量上限约 400 万,对 99.9% 的应用不构成限制

Project Lilliput

JEP 534 是 Project Lilliput 的阶段性成果,是一场三年的“瘦身”工程。该项目由 Red Hat 的 Roman Kennke 于 2021 年发起,目标是将 Java 对象头从 128 bits 一步步压缩到 64 bits,最终甚至到 32 bits

阶段JDK 版本里程碑
基础设施JDK 22引入 Object Monitor Tables
实验阶段JDK 24JEP 450 实验性紧凑对象头
正式产品JDK 25JEP 519 正式集成,手动开启
默认开启JDK 27JEP 534 设为默认
未来目标TBDLilliput 2,32-bit 对象头

也就是说,紧凑对象头压缩还远没有到终点。

很多优秀的特性,背后都有不少大厂的声音,JEP 534 也不例外。

Amazon 的工程团队表示,他们将紧凑对象头回移植到 JDK 17 和 JDK 21 后,在数百个生产服务中验证了稳定性和性能收益,这种现实世界的验证影响了将特性集成到 JDK 25 的决定

SAP 的 SapMachine 更是“抢先一步”,已经默认开启紧凑对象头,每天运行大量客户场景测试,为社区提供了宝贵的兼容性数据。

这也是支撑 JDK 27 中,把它默认的最重要原因之一。

总结

JEP 534 可能是 JDK 27 中最“润物细无声”的特性之一,是一次“零成本”的性能跃升。

  • 无需改代码,纯 JVM 层优化
  • 无需调参数,JDK 27 默认生效
  • 内存降低 20%+,堆更省、GC 更少
  • CPU 降低 8-30%,缓存更高效、计算更省
  • 云成本直接节省,容器密度提升、资源利用率更高

我知道,有些人可能会说,只是改了一个“默认”开启,但这背后却能影响到无数个后续升级到 JDK 29 等长 lts 版本的小企业用户,受益的是整个 Java 生态。

现在,对于运行在云原生环境、微服务架构、内存敏感型应用中的 Java 开发者来说,JDK 27 的这次升级,堪称免费午餐

正如 JEP 534 所言,We intend to deprecate the old object header layout in a future release.(我们打算在未来版本中废弃旧的对象头布局。)紧凑对象头,就是 Java 对象内存布局的未来。

非常期待 Lilliput 项目进行推进,早日落地“32 bit 对象头”这一目标。

参考资料

  • JEP 534: Compact Object Headers by Default https://openjdk.org/jeps/534
  • JDK 27 Project Page https://openjdk.org/projects/jdk/27/
  • JEP 519: Compact Object Headers https://openjdk.org/jeps/519

业余草公众号

最后,欢迎关注我的个人微信公众号:业余草(yyucao)!可加作者微信号:xttblog2。备注:“1”,添加博主微信拉你进微信群。备注错误不会同意好友申请。再次感谢您的关注!后续有精彩内容会第一时间发给您!原创文章投稿请发送至532009913@qq.com邮箱。商务合作也可添加作者微信进行联系!

本文原文出处:业余草: » JVM 再瘦身,JDK 27 对象头公摊面积暴降 33%,CPU 降 30%