使用jstat和jmap分析G1需结合GC日志与JVM参数交叉验证;jstat -gc与-gccause组合才能区分Young/Mixed/Full GC,S0C/S1C等字段在G1中无意义应忽略。

使用 jstat 和 jmap 分析 G1 垃圾收集器的运行状态,核心在于理解 G1 的内存结构(如分区 Region、Remembered Set、Humongous 对象等)以及各工具输出字段的实际含义。单纯看命令结果容易误判,关键是要结合 GC 日志、应用行为和 JVM 参数交叉验证。
用 jstat 实时观察 G1 的 GC 频率与停顿表现
jstat -gc <pid> 是最常用的起点,但对 G1 来说,必须使用 -gc 和 -gccause 组合,因为 G1 的 GC 类型(Young GC / Mixed GC / Full GC)直接影响调优方向:
-
S0C/S1C、EC/OC在 G1 中不反映真实堆布局(G1 不分新生代/老年代连续空间),这些列恒为 0 或无意义,应忽略 - YGCT(Young GC 总耗时)、
FGCT(Full GC 次数)、GCT(所有 GC 总耗时)——若FGCT > 0,说明 G1 已退化,需紧急排查原因(如 Humongous 分配失败、并发标记失败、RSet 扫描超时等) -
jstat -gccause <pid> 1s可每秒刷新,重点看LGCC(Last GC Cause)列:例如G1 Evacuation Pause表示正常 Young 或 Mixed GC;Allocation Failure是触发原因,但不区分类型;Concurrent Cycle Initiated表示并发标记启动
用 jmap 定位大对象与内存分布异常
jmap 对 G1 的分析价值不在堆快照本身(jmap -histo 仍有效),而在于识别两类 G1 特有风险:
DMap GL地图JSAPI(dmapgl)开发指南。用于编写、审查、调试 DMap 地图 API 代码,涵盖地图初始化、覆盖物渲染、图层管理、事件处理、控件交互等任务。当用户提及 dmap、dmapgl、jsapi‑gl 或相关地图开发需求时自动触发。
-
jmap -histo:live <pid>查看存活对象分布,重点关注[B(byte[])、[I(int[])等数组类型实例数和总大小——G1 中超过 Region 一半大小的对象会被直接分配到 Humongous 区,频繁出现大数组可能引发 Humongous 分配失败(导致 Full GC) -
jmap -clstats <pid>检查类加载器对象数量,避免 ClassLoader 泄漏——G1 下泄漏的类元数据会堆积在 Metaspace,但若伴随大量动态代理或 OSGi 场景,也可能间接加剧 GC 压力 - 慎用
jmap -dump:G1 堆可能达数十 GB,dump 文件极大且分析耗时;如必须 dump,优先用jmap -dump:format=b,file=heap.hprof,live <pid>确保只抓活跃对象,减少噪声
必须配合 GC 日志才能准确定义问题
jstat 和 jmap 是“症状观测器”,GC 日志才是“病历本”。开启 G1 日志的关键参数:
-
-Xlog:gc*:file=gc.log:time,tags,level(JDK 10+)或-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:gc.log(JDK 8) - 重点关注日志中的
[GC pause (G1 Evacuation Pause) (young)和(mixed)区分类型;to-space-exhausted表示 Mixed GC 中 To 区不足;humongous allocation明确标出大对象分配位置 - 对比
jstat中的 GC 时间与日志中具体阶段耗时(如[Ext Root Scanning]、[Update RS]、[Scan RS]),可定位瓶颈:若 Update RS 耗时长,说明 RSet 更新频繁,可能需调大-XX:G1RSetUpdatingPauseTimePercent
几个典型误判场景提醒
实际分析中容易掉进这些坑:
- 看到
jstat -gc中OC(Old Capacity)数值波动就认为老年代在增长——G1 中 OC 列无效,真正老年代使用量要看 GC 日志里的old:区间或jstat -gcold(JDK 8u262+ 支持) - 用
jmap -histo发现某个类实例多,直接断定是内存泄漏——G1 下需确认该类是否被正确回收(看下一次 Young GC 后是否减少),并检查其引用链(用 MAT 分析 dump 时的 dominator tree) - 仅凭
jstatGC 频率低就认为 G1 运行健康——可能因-XX:MaxGCPauseMillis设得过高,导致 GC 周期拉长、堆占用持续攀升,最终触发长时间 Mixed GC 或 Full GC

















