Epsilon GC的设计初衷是暴露真相而非运行程序,它只分配内存、不回收、不移动、不触发清理,堆满即退出,专用于剥离GC干扰的微基准测试;必须同时配置-Xmx、-XX:+UnlockExperimentalVMOptions和-XX:+UseEpsilonGC三要素,JVM退出即有效数据点,崩溃时长与退出码构成核心测量指标。

Epsilon GC 的设计初衷不是为了“运行程序”,而是为了“暴露真相”——它不回收、不移动、不触发任何清理逻辑,只做一件事:分配内存,直到堆满就退出。这种极致的“无操作”特性,让它成为微基准测试中剥离 GC 干扰、直击代码本质行为的利器。
设计初衷:消除不确定性,回归内存分配本源
Epsilon 是 JEP 318 引入的实验性收集器,核心哲学是提供一个“完全消极”的 GC 实现。它不参与标记、清除、压缩、写屏障或并发线程调度,也不响应 System.gc()。它的存在只为回答三个底层问题:
- 这段代码到底创建了多少对象?
- 对象从分配到 JVM 终止,真实驻留了多久?
- 在零 GC 干扰下,纯分配与访问路径的延迟/吞吐极限在哪?
它把 JVM 堆变成一块确定性裸资源,让延迟毛刺、内存抖动、屏障开销全部归零,从而将性能瓶颈真正锚定在业务逻辑、JIT 编译、锁竞争或硬件层面上。
微基准测试中的关键配置:三要素缺一不可
启用 Epsilon 不是加一个参数那么简单。必须同时满足以下三项,否则启动失败或行为失真:
立即学习“Java免费学习笔记(深入)”;
- -XmxN:硬性设定堆上限(如 -Xmx256m),这是 Epsilon 的“撞墙刻度尺”,没有它就没有可复现的退出信号
- -XX:+UnlockExperimentalVMOptions:JDK 11–15 必须显式解锁实验特性,漏掉会报 Unrecognized VM option 'UseEpsilonGC'
- -XX:+UseEpsilonGC:唯一启用开关,不能与其他 GC 参数(如 -XX:+UseG1GC)共存
完整命令示例:
java -Xmx256m -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC -jar benchmark.jar
在微基准中如何用好“崩溃”这个数据点
Epsilon 下的 JVM 退出不是故障,而是有效测量终点。关键在于把退出行为转化为结构化指标:
- 记录退出码(137 或 143)和精确运行时长,例如“-Xmx512m 下运行 9.3 秒后退出” → 表明该逻辑在 512MB 内最多支撑 9.3 秒持续分配
- 对比优化前后相同配置下的退出时间:若从 7.1 秒提升至 10.8 秒,说明单位时间对象生成率下降约 34%,验证低垃圾设计效果
- 配合 Runtime.getRuntime().totalMemory() - freeMemory() 实时采样,确认是否逼近 -Xmx 阈值,避免误判为其他资源耗尽
避坑要点:微基准里最容易踩的四个误区
很多微基准结果失真,并非代码问题,而是误用了 Epsilon 的语义:
- 依赖 finalize()、WeakReference 或 PhantomReference 判断对象生命周期 → 它们在 Epsilon 下永不触发,引用永远不入队
- 用 jstat -gc 查 GC 统计 → Epsilon 没有 GC 事件,该命令输出为空或报错;应改用 jcmd <pid> VM.native_memory summary
- 未禁用其他 GC 相关参数(如 -XX:MaxGCPauseMillis)→ 这些对 Epsilon 无效,但可能引发警告甚至干扰启动
- 在短生命周期任务中忽略容器环境限制 → Kubernetes 中需设置 securityContext.procMount: "Unmasked",否则 /proc 下的 RSS 和 CPU 统计不准


















