【JVM】相关排查命令【一】JVM 故障排查全套 Linux 命令、参数、实战案例【1】前置说明1jps定位 Java 进程 PID入口命令2top /htop定位 CPU 占用高的 Java 线程1-top系统自带无需额外安装2-htop可视化需 yum install htop3jstack打印线程堆栈排查 CPU 高、死锁、阻塞4jstat轻量实时监控 GC、分代内存线上最常用无性能损耗1-jstat -gc PID 间隔毫秒 打印次数2-jstat -gccapacity PID 10003-jstat -gcmetacapacity PID 10004-jstat -gcutil PID 10005jmap堆内存快照、查看内存占用排查 OOM1-jmap -heap PID轻量查看堆分代配置不生成 dump2-jmap -histo PID轻量堆对象统计不拉完整 dump3-jmap -dump:formatb,filexxx.hprof PID 生成堆快照4-jmap -clstats PID类加载统计排查元空间6free /df/vmstat系统底层资源排查【二】GC 日志完整分析方法区分新生代 / 老年代 / 元空间问题【1】JVM GC 日志开启参数生产必配【2】GC 日志关键字段解读1Young GC 日志样例2Full GC 日志样例危险【3】如何判断哪个区域出问题1新生代 Eden 问题2老年代 Old Gen 问题堆内存泄漏3元空间 Metaspace 问题元空间泄漏4补充区分特征【三】堆内存监控轻量分析方案不生成 dump 大文件方案 1jstat 持续监控生产首选零 IO、低性能损耗方案 2jmap -heap 查看分代配置与实时占用方案 3jmap -histo 轻量对象统计定位泄漏对象方案 4可视化轻量工具 Arthas阿里开源推荐线上【四】Heap Dumphprof快照是否包含元空间数据细分说明如果要完整分析元空间问题配套方案补充OOM 元空间时仅靠 hprof 不够【五】完整排查流程总结【一】JVM 故障排查全套 Linux 命令、参数、实战案例【1】前置说明所有命令依赖 JDK 自带工具包jps/jstack/jstat/jmap/jhat需和运行 Java 进程同版本 JDK且进程同用户。1jps定位 Java 进程 PID入口命令作用列出本机所有 Java 进程、PID、主类名、JVM 参数常用参数jps -l输出完整主类全限定名最常用jps -m输出 main 方法入参jps -v输出进程启动全部 JVM 参数Xmx/Xss/ 元空间参数等jps -q只输出 PID脚本批量处理用实战案例# 查看所有Java进程完整类名jps-l# 输出示例12568com.server.Application9872org.apache.tomcat.startup.Bootstrap# 查看进程12568的所有JVM启动参数jps-v125682top /htop定位 CPU 占用高的 Java 线程1-top系统自带无需额外安装作用查看整机 CPU、内存找到高 CPU PID再定位内部高消耗线程核心操作与参数top# 进入面板Shift P# 按CPU使用率排序Shift M# 按内存占用排序1# 展开多核CPU完整排查 CPU 飙高流程案例# 1. top 找到Java进程PID12568top# 2. 单独只监控该进程top-p12568# 3. 导出该进程下所有线程nid十六进制用于jstack匹配top-H-p12568# 4. 假设高CPU线程nid3241转16进制printf %x\n 3241printf%x\n3241# 输出 c91# 5. jstack打印堆栈搜索0xc91定位死循环/频繁GC线程jstack12568thread.loggrep-A20c91 thread.log2-htop可视化需 yum install htophtop-p12568# F6 按CPU排序直接看线程占用3jstack打印线程堆栈排查 CPU 高、死锁、阻塞作用导出所有线程栈定位死循环、死锁、阻塞、GC 线程耗时常用参数jstack PID普通堆栈jstack -l PID额外输出锁持有信息排查死锁必用jstack -F PID进程假死、阻塞无响应时强制 dump 线程实战案例# 导出线程栈到文件jstack-l12568jstack_$(date%Y%m%d_%H%M).log# 连续3次打印堆栈对比线程状态排查持续CPU高jstack12568stack1.logsleep2jstack12568stack2.logsleep2jstack12568stack3.log# 对比同一线程是否一直RUNNABLE死循环常见问题关键字RUNNABLE循环业务代码 → 业务死循环 CPU 高WAITING / BLOCKED→ 锁竞争、死锁GC Thread大量占用 → GC 频繁导致 CPU 飙升4jstat轻量实时监控 GC、分代内存线上最常用无性能损耗核心三大用法jstat -gc/-gccapacity/-gcmetacapacity1-jstat -gc PID 间隔毫秒 打印次数作用实时输出新生代、老年代、元空间内存、GC 次数、耗时轻量监控首选无需 dump字段说明S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT S0C/S1CSurvivor总容量S0U/S1U已使用 EC/EUEden总容量/已用 OC/OU老年代总容量/已用 MC/MU元空间总容量/已使用 YGC/YGCTYoungGC总次数、总耗时 FGC/FGCTFullGC总次数、总耗时 GCTGC总耗时实战案例# 每500ms打印一次GC状态持续输出jstat-gc12568500# 每1秒打印输出20次后停止jstat-gc12568100020判断问题技巧OU老年代已用持续上涨FGC 持续增多 → 堆内存泄漏MU元空间已用只涨不跌FGC 频繁 → 元空间泄漏YGC 次数极多YGCT 耗时高 → Eden 过小分配对象过快FGCT 持续走高每次 FullGC 停顿久 → 老年代不足 / 元空间达阈值2-jstat -gccapacity PID 1000查看各代内存容量、最大阈值Xmx、MaxMetaspaceSize 生效值3-jstat -gcmetacapacity PID 1000专门监控元空间MC/MU、MCMX最大元空间、类加载卸载数量排查元空间泄漏专用4-jstat -gcutil PID 1000百分比展示内存使用率直观S0 S1 E O M CCS YGC YGCT FGC FGCT GCT0.0088.3212.4576.2392.1289.11321015.2104228.32043.530O76%、M92% 代表老年代、元空间占用极高马上 OOM5jmap堆内存快照、查看内存占用排查 OOM1-jmap -heap PID轻量查看堆分代配置不生成 dump作用打印堆整体配置、新生代 / 老年代 / 元空间容量、收集器类型轻量无 IO 开销案例jmap-heap12568# 输出Xms/Xmx、Eden/Survivor比例、MaxTenuringThreshold、Metaspace配置、GC收集器2-jmap -histo PID轻量堆对象统计不拉完整 dump作用实时打印堆内所有对象类型、实例数量、占用内存大小快速定位大对象 / 泄漏对象# 输出到文件分析jmap-histo12568histo.log# 只看前30行占用最大的对象head-30histo.log字段序号 | 实例数量 | 占用字节 | 类名发现自定义业务类持续大量创建 堆泄漏3-jmap -dump:formatb,filexxx.hprof PID 生成堆快照作用导出完整堆 dump 文件用于 MAT 深度分析# 导出堆快照到指定路径jmap-dump:formatb,file/data/heap_$(date%Y%m%d).hprof12568# OOM自动dump参数启动JVM时配置无需手动执行命令-XX:HeapDumpOnOutOfMemoryError-XX:HeapDumpPath/data/dump4-jmap -clstats PID类加载统计排查元空间输出加载类总数、卸载数量、元空间占用6free /df/vmstat系统底层资源排查free-h# 整机物理内存、SwapSwap持续上涨说明内存不足vmstat1# 每秒系统IO、内存、CPUsi/so代表swap交换频繁GC卡顿df-h# 磁盘满会导致dump文件无法生成、GC日志写失败【二】GC 日志完整分析方法区分新生代 / 老年代 / 元空间问题【1】JVM GC 日志开启参数生产必配# 基础GC日志-XX:PrintGCDetails-XX:PrintGCTimeStamps-XX:PrintGCDateStamps-Xloggc:/data/logs/gc-%t.log# 打印元空间、类卸载日志-XX:PrintMetaspaceStatistics-XX:TraceClassUnloading# 打印GC前后各代内存-XX:PrintHeapAtGC【2】GC 日志关键字段解读1Young GC 日志样例2026-07-17T10:00:00.1230800:12345.123:[GC(Allocation Failure)[PSYoungGen: 81920K-800K(92160K)]120000K-40880K(194560K),0.012345secs][Metaspace: 32100K-32100K(108032K)]拆解Allocation FailureEden 区满分配新对象失败触发 YoungGCPSYoungGen: 81920K-800K新生代 GC 前 80M回收后 0.8M回收效果好整体堆120000K→40880KMetaspace:32100K-32100K元空间无变化本次不处理类卸载2Full GC 日志样例危险2026-07-17T10:01:00.4560800:12400.456:[Full GC(Metadata GC Threshold)[PSYoungGen: 6000K-0K(92160K)][ParOldGen: 80000K-78000K(102400K)]86000K-78000K(194560K),[Metaspace: 45000K-44800K(108032K)],0.567890secs]触发原因Metadata GC Threshold元空间占用达到 MetaspaceSize 阈值强制 FullGC【3】如何判断哪个区域出问题1新生代 Eden 问题日志特征频繁GC (Allocation Failure)YGC 每分钟几十上百次Eden 区 EU 快速打满每次 YGC 回收大量内存但很快再次占满根因对象创建速度过快接口并发高、循环创建临时对象-Xmn新生代内存设置过小现象YGC 频繁轻微 STWCPU 小幅升高2老年代 Old Gen 问题堆内存泄漏日志特征每次 YGC 后 OU老年代已用持续阶梯上涨FullGC 次数逐步增多FullGC 前后老年代内存几乎无下降ParOldGen:80000K-79500K最终抛出Java heap space OOM根因静态集合、ThreadLocal、缓存未清理对象长期存活晋升老年代无法回收3元空间 Metaspace 问题元空间泄漏日志关键字FullGC 触发原因Metadata GC Threshold/Metaspace allocation failureGC 日志中Metaspace: 42000K-41980K回收几乎无释放jstat -gc MU 持续单向上涨类卸载日志极少或无根因热部署、CGLIB 动态代理、自定义 ClassLoader 未释放类无法卸载最终报错java.lang.OutOfMemoryError: Metaspace4补充区分特征表格故障区域GC 核心特征jstat 表现新生代YGC 极其频繁OU 稳定EU 快速起落OU 平稳老年代泄漏FGC 持续增加FullGC 回收空间极少OU 只涨不跌元空间泄漏大量 FullGC 由 Metadata 阈值触发MU 持续上涨无回落【三】堆内存监控轻量分析方案不生成 dump 大文件方案 1jstat 持续监控生产首选零 IO、低性能损耗组合命令实时观测三代内存变化无需快照# 每1秒输出GC使用率元空间状态jstat-gcutil125681000# 单独监控元空间jstat-gcmetacapacity125681000适用场景线上持续观测内存走势判断是否泄漏。方案 2jmap -heap 查看分代配置与实时占用瞬时打印新生代、老年代、元空间总容量、当前使用量无文件生成秒级返回。方案 3jmap -histo 轻量对象统计定位泄漏对象导出所有对象数量与内存占用文件远小于 hprof 快照快速定位自定义业务大对象jmap-histo12568histo.log# 过滤业务自定义类grepcom.yourpackagehisto.log方案 4可视化轻量工具 Arthas阿里开源推荐线上无需重启进程attach 后实时监控分代、GC、对象无大 dump 文件核心命令# 查看堆各区域实时占用memory# 实时GC监控gc-i1000# 统计对象创建排行heapdump--live/tmp/tmp.hprof# 可选只dump存活对象文件更小优势支持在线查看类加载数量、元空间占用、线程状态不用记忆大量 Linux 原生命令。【四】Heap Dumphprof快照是否包含元空间数据结论标准jmap -dump堆快照不包含完整元空间类元数据细分说明hprof 包含内容Java 堆所有对象、数组、Class 实例堆中的java.lang.Class对象静态变量、ThreadLocal、字符串常量池、对象引用链hprof不包含元空间底层原始类元数据字节码、运行时常量池、方法表、字段信息ClassLoader、类加载卸载统计、本地内存 Chunk 分配信息如果要完整分析元空间问题配套方案轻量排查元空间jstat -gcmetacapacityjmap -clstats GC 日志-XX:TraceClassUnloading深度分析类加载泄漏导出 GC 日志看类卸载记录使用 Arthasclassloader命令查看各加载器加载类数量MAT 打开 hprof 可查看堆内 ClassLoader 实例但看不到元空间底层字节码数据补充OOM 元空间时仅靠 hprof 不够元空间泄漏根源是 ClassLoader 无法回收hprof 只能看到堆里的 ClassLoader 对象完整判断必须配合 GC 日志、类加载统计、jstat 元空间监控三者结合。【五】完整排查流程总结jps -l获取 Java PIDCPU 飙高top -H定位高 CPU 线程 →jstack匹配线程栈区分业务死循环 / GC 线程消耗频繁 FullGC / 内存缓慢上涨jstat -gcutil 1000持续观测新生代、老年代、元空间走势怀疑堆泄漏jmap -histo轻量分析对象确认泄漏后生成 hprof 快照用 MAT 分析怀疑元空间泄漏查看 GC 日志 Metadata 触发的 FullGC、jstat -gcmetacapacity、类卸载日志OOM 事后复盘启用-XX:HeapDumpOnOutOfMemoryError自动生成 dump同时留存完整 GC 日志