jstat用于实时监控内存变化趋势,jmap用于精准定位内存占用元凶,二者配合可高效诊断内存问题:jstat关注ou、fgct等指标发现泄漏苗头,jmap-histo:live统计存活对象锁定嫌疑类,再结合dump与mat分析引用链追溯泄漏根源。

内存溢出不是突然发生的,而是长期积累的结果。jstat 能帮你“看见趋势”,jmap 则帮你“锁定元凶”——两者配合,才是诊断内存问题的正确打开方式。
jstat 实时盯住内存变化,发现异常苗头
jstat 不干扰应用运行,适合在生产环境持续观察。关键不是看单次数值,而是看变化节奏:
- 重点关注 OU(老年代使用量)和 FGCT(Full GC 耗时):如果 OU 持续上升、FGCT 频次增加且每次耗时变长,说明对象正在堆积且难以回收,大概率存在泄漏或大对象驻留
- 留意 EU(伊甸园区使用率)是否长期卡在高位却不触发 YGC:这可能意味着 Eden 区设置过大,或应用实际创建对象极少,需结合业务逻辑判断是否合理
- 用 jstat -class 查类加载趋势:Loaded 类数持续增长、Unloaded 几乎为 0,可能是 ClassLoader 泄漏,尤其在热部署频繁或动态代理多的场景
jmap 快速定位“谁占了最多内存”
当 jstat 提示异常后,立刻用 jmap 精准扫描堆中对象分布:
-
jmap -histo:live
:只统计当前存活对象,结果按占用字节倒序排列。重点关注排在前几的数组类型(如 [B、[C)、String、HashMap$Node 或业务自定义类 - 注意对象描述符含义:[B 是 byte[],[C 是 char[],[I 是 int[],L开头如 Ljava/lang/String; 表示类实例;数组类名含 [L 表示对象数组
- 对比两次 histo 输出:间隔几分钟分别执行,若某类实例数/字节数明显增长且不回落,基本可圈定嫌疑对象
jmap dump + MAT 深度分析泄漏路径
当怀疑存在泄漏但 histo 不够明确时,导出堆快照交给专业工具分析:
-
生成 dump 文件:jmap -dump:format=b,file=heap.hprof
。注意磁盘空间充足,文件通常数百 MB 起 - 优先用 MAT 打开:加载后先看 “Leak Suspects” 报告,它会自动标出最可能的泄漏点;再进 “Dominator Tree”,按 retained heap 排序,找持有大量子对象的根节点
- 顺着引用链往回查:右键对象 → “Path to GC Roots” → 选择 “with all references”,重点看哪些静态变量、缓存容器、监听器或线程局部变量意外持有了本该释放的对象
操作注意事项与避坑提醒
工具好用,但用错时机或权限容易白忙一场:
- jmap -histo 默认不加 :live 会统计所有对象(含待回收),干扰判断,线上排查务必加 :live
- jmap dump 会触发全局 safepoint,导致应用短暂卡顿,避开高峰期;容器环境需提前配置 --cap-add=SYS_PTRACE
- 普通用户只能 attach 自己启动的 Java 进程,排查他人进程需 root 权限或协调运维协助
- 别等 OOM 才行动:可在 JVM 启动时加上 -XX:+HeapDumpOnOutOfMemoryError,让崩溃时自动保存现场










