Java Flight Recorder(JFR)是定位内存分配热点和潜在泄漏的高效手段——它不依赖堆转储,而是通过持续、低开销的运行时事件采集,精准反映对象“在哪创建”“活了多久”“为何没被回收”。

Java Flight Recorder(JFR)是定位内存分配热点和潜在泄漏的高效手段——它不依赖堆转储,而是通过持续、低开销的运行时事件采集,精准反映对象“在哪创建”“活了多久”“为何没被回收”。关键在于启用合适事件、聚焦核心视图、结合上下文交叉验证。
开启带分配追踪的JFR录制
默认 profile 配置已包含基础分配事件,但要深度分析热点与长期存活对象,需显式增强配置:
- 启动时启用(推荐测试/预发环境):
java -XX:+FlightRecorder \
-XX:StartFlightRecording=duration=120s,filename=mem-analysis.jfr,settings=profile,stackdepth=256 \
-jar app.jar
其中stackdepth=256确保能捕获完整的调用栈,对定位 new 操作位置至关重要。 - 运行时动态开启(生产首选):
jcmd <pid> JFR.start name=alloc-trace settings=profile filename=/tmp/alloc.jfr stackdepth=256 maxsize=200M - 若怀疑老年代对象堆积,可额外启用采样:
jcmd <pid> VM.native_memory summary 辅助判断是否为原生内存问题;
同时确保 JFR 包含jdk.ObjectAllocationInNewTLAB和jdk.ObjectAllocationOutsideTLAB事件。
在JMC中定位分配热点
用 JDK Mission Control 打开 .jfr 文件后,直接进入 Memory → Object Statistics:
- 按 Allocated Objects 降序排列,关注前几类:如
byte[]、String、HashMap$Node或自定义业务类(如WxMessage); - 点击某类 → 右键 Show Allocation Stack Trace,查看哪些方法路径频繁触发该类实例化;
- 切换到 Code → Hot Methods,筛选 “Allocation” 列高的方法,确认是否在循环、高频接口或日志构造中反复 new 对象。
识别潜在泄漏的关键线索
分配多不等于泄漏,真正可疑的是“持续增长且难以回收”的对象。重点关注以下信号:
立即学习“Java免费学习笔记(深入)”;
- Old Gen 使用率缓步上升:在 Memory → Memory Pool Usage 中观察 Old Gen 曲线,若每次 Full GC 后未回落,或回落幅度越来越小,高度提示泄漏;
- OldObjectSample 事件:在 Event Browser 中搜索该事件,查看存活超 5 分钟的对象类型及堆栈——若大量业务对象出现在此,说明它们被强引用链长期持有;
-
GC Roots 引用链缺失释放点:对可疑类右键 → Inspect Instances → 任选一个实例 → References → Show Retained Set,观察是否被
static字段、未清理的ThreadLocal、监听器或缓存容器(如无 TTL 的ConcurrentHashMap)直接/间接持有。
辅助验证与收敛判断
单靠 JFR 有时难下定论,需配合其他动作缩小范围:
- 录制期间手动触发多次 GC(jcmd <pid> VM.gc),再对比前后 Object Statistics 中同类对象数量变化;
- 使用 jfr print --events jdk.OldObjectSample recording.jfr 导出文本,快速 grep 关键类名,统计样本数趋势;
- 若确认是缓存类泄漏(如
MessageCacheService),检查代码中是否有CACHE.clear()调用点缺失、TTL 未设置、或清理逻辑被异常跳过。


















