测试环境:OpenCloudOS 8.10, x86_64, 4 core, JDK 25.0.4, G1 GC, 堆 1G / 512M
压测项目:RuoYi-Vue(Spring Boot 4.0.6)
数据仅供参考,不同硬件/负载/配置下结果会不同
一、先说结果
先给结论:稳定态堆占用 204MB → 165MB(-19.1%),最大 GC 暂停 36ms → 24ms(-33%),吞吐基本无损耗。这些数字都来自同一个 jar、同样堆、同样压测,唯一变量是加不加一个参数。
实验设计很简单:同一个 RuoYi-Vue 的 jar 包,同样的堆、同样的 GC、同样的压测,唯一区别就是加不加-XX:+UseCompactObjectHeaders这个参数。
这个参数就是 JDK 25 的 Compact Object Headers(JEP 519),中文叫「紧凑对象头」。它做的事一句话就能说清:把每个 Java 对象的对象头从 12 字节压到 8 字节。
先看最直观的指标——稳定态堆占用:
| 组别 | 堆使用量 |
|---|---|
| 默认对象头 | 204 MB |
| 紧凑对象头 | 165 MB |
![[对象头_堆占用对比.png]]
省了 39MB,降幅 19.1%。
RuoYi 启动后加载一大票缓存——字典、菜单、权限、岗位,全是小对象。这些对象驻留在堆里,头部从 12 字节缩到 8 字节,省下的就是实打实的内存。
再看第二个数据。我把堆缩到 512M、压测加到 6 万请求,逼出更频繁的 GC,结果发现了一个更有意思的现象:
| 指标(512M 堆) | 默认头 | 紧凑头 |
|---|---|---|
| 最大 GC 暂停 | 36.06 ms | 24.12 ms |
| 平均 GC 暂停 | 12.12 ms | 10.65 ms |