【大白话说Java面试题 第68题】【JVM篇】第28题:对于 JDK 自带的监控和性能分析工具用过哪些?一般你怎么用的?
📌PDF:大白话说Java面试题 — 02-JVM篇
第28题:对于 JDK 自带的监控和性能分析工具用过哪些?一般你怎么用的
📚回答:
- 核心考点:
大厂面试要求熟练掌握 JDK 自带工具,并能结合场景说明使用时机、命令参数、结果解读。不能只会罗列工具名称。
1. 工具全景图
| 工具 | 核心用途 | 是否需要目标进程 | 是否STW |
|---|---|---|---|
jps | 列出 Java 进程 PID | 是 | 否 |
jinfo | 查看/修改 JVM 参数 | 是 | 否 |
jstat | GC 和内存区域实时统计 | 是 | 否 |
jmap | 堆内存快照(dump) | 是 | 是(严重) |
jstack | 线程堆栈快照 | 是 | 否(但可能略慢) |
jcmd | 多功能综合工具(JDK 7+) | 是 | 部分操作会 |
VisualVM | 图形化综合监控 | 是(可本地/远程) | 采样模式不影响 |
2. 各工具典型用法(附命令)
2.1jps:定位目标进程
jps-l# 显示完整主类名jps-v# 显示传递给 JVM 的参数场景:启动分析前第一步,拿到 PID。
2.2jstat:实时监控 GC(最常用)
# 每1秒打印一次,共打印10次jstat-gcutil<PID>100010# 输出列解读:# S0/S1: Survivor 使用率# E: Eden 使用率# O: 老年代使用率# M: 元空间使用率# YGC/YGCT: Young GC 次数/总耗时# FGC/FGCT: Full GC 次数/总耗时# GCT: GC 总耗时实战判断:
YGC每分钟超过60次 → 年轻代太小FGC每小时 >1 次 → 需排查(除非元空间/堆合理调优后仍存)GCT / 运行时长> 10% → GC 已严重影响吞吐
2.3jmap:堆内存快照(谨慎使用)
# 生成 dump 文件(会触发 Full GC,生产需低峰期)jmap -dump:live,format=b,file=/tmp/heap.hprof<PID># 查看对象统计(不会 dump 大文件,但仍会 STW)jmap-histo:live<PID>|head-30⚠️ 重要:
-dump:live会先触发 Full GC,STW 时间可能达数秒甚至分钟- 生产环境优先用
-XX:+HeapDumpOnOutOfMemoryError自动 dump - 高并发系统用
jcmd <PID> GC.heap_dump /path/dump.hprof(底层同 jmap,依然 STW)
分析 dump:用MAT(Eclipse Memory Analyzer)或VisualVM查看 Leak Suspects、Dominator Tree。
2.4jstack:线程快照(无痛)
# 导出线程栈jstack-l<PID>>thread.dump# 快速统计线程状态grep"java.lang.Thread.State"thread.dump|sort|uniq-c经典用法:
- CPU 飙高:
top -H -p <PID>找线程 ID(十进制的) →printf "%x\n" <十进制tid>→ 在 jstack 输出中搜索十六进制 tid - 死锁:jstack 输出末尾会直接报告“Found one Java-level deadlock”
- 接口超时:连续多次打印 jstack,对比 WAITING/BLOCKED 线程是否一直卡在同一位置
2.5jinfo:查看运行时参数
# 查看所有可设置参数及当前值jinfo-flags<PID># 查看单个参数jinfo-flagUseG1GC<PID># 动态修改(部分参数支持)jinfo-flag+HeapDumpOnOutOfMemoryError<PID>场景:线上验证-Xmx是否生效、某个 GC 参数是否真的被打开。
2.6jcmd:新一代瑞士军刀(JDK 7+ 推荐)
# 列出所有可执行命令jcmd<PID>help# 查看 JVM 运行时参数(替代 jinfo -flags)jcmd<PID>VM.flags# 手动触发 GC(慎用,仅测试)jcmd<PID>GC.run# 获取系统属性jcmd<PID>VM.system_properties# 获取线程栈(同 jstack)jcmd<PID>Thread.print# 生成 heap dumpjcmd<PID>GC.heap_dump /tmp/dump.hprof# 查看 Native 内存(诊断直接内存/堆外)jcmd<PID>VM.native_memory summary优势:统一入口,输出结构更清晰,部分操作比 jmap 更安全。
2.7VisualVM:图形化利器
连接方式:
- 本地:自动检测本机 Java 进程
- 远程:通过 JMX(需开启
-Dcom.sun.management.jmxremote)
常用 Tab:
- Monitor:CPU/堆/元空间/类/线程 实时曲线
- Threads:线程状态及堆栈,可检测死锁
- Sampler:CPU 采样 → 热点方法;内存采样 → 对象分配统计
- Profiler(需插件):更精确但开销大,生产慎用
生产远程连接示例(JMX 参数):
-Dcom.sun.management.jmxremote=true\-Dcom.sun.management.jmxremote.port=9999\-Dcom.sun.management.jmxremote.authenticate=false\-Dcom.sun.management.jmxremote.ssl=false3. 实战案例:生产 Full GC 频繁排查
现象:服务 GC 报警,FGC每小时 12 次,老年代占用率 95% 不降。
步骤:
| 步骤 | 工具 | 命令 | 发现 |
|---|---|---|---|
| 1 | jps | jps -l | PID 12345 |
| 2 | jstat | jstat -gcutil 12345 1000 | O(老年代)始终 98%,FGC 持续增长 |
| 3 | jmap(低峰期) | jmap -histo:live 12345 | head -20 | byte[]占 80%,自定义SessionCache对象异常多 |
| 4 | jstack | jstack 12345 > t.dump | 大量线程在SessionCache.put等待锁 |
| 5 | 定位代码 | 结合业务日志 | 缓存未设过期时间,且未限制最大容量 |
| 6 | 修复 | 代码:改用Caffeine缓存 + TTL | 上线后 FGC 降为 0 |
4. 面试官追问示例
Q1:jmap -histo:live会触发 Full GC 吗?
A:会。live参数会先执行一次 Full GC 再统计存活对象。生产环境慎用,优先用jstat看趋势或 Arthasheapdump。
Q2:jstack打印出的BLOCKED线程很多,一定有问题吗?
A:不一定。若BLOCKED是瞬时锁竞争且正常情况(如synchronized高并发),只要不持续堆积就正常。需多次打印确认是否一直卡在同一锁。
Q3:远程连接 VisualVM 不安全怎么办?
A:生产禁止明文 JMX。替代方案:
- 用
jstat/jstack本地执行后导出分析 - 用 Arthas(阿里开源)隧道连接
- 开启 JMX + SSL 认证(复杂)
Q4:jcmd能完全替代jmap吗?
A:大部分可以。jcmd GC.heap_dump同jmap -dump,但jcmd VM.native_memory是 jmap 没有的功能。不过jmap -histo的快速对象统计,jcmd 没有直接等价命令。
Q5:生产环境不能安装任何额外工具,只有 JDK 自带,怎么排查?
A:就用jps/jstat/jstack/jmap/jcmd组合。例如:
- CPU 高 →
top -H -p PID+jstack - 内存泄漏 →
jstat -gcutil看 O 区持续增长 +jmap -dump:live(择低峰期) - GC 频繁 →
jstat -gc看明细
💡面试官想要的满分总结:
“日常问题排查,我按以下组合使用:
- jps找 PID
- jstat -gcutil看 GC 趋势,决定是否需要 dump
- jstack查线程阻塞/死锁/热点栈
- jmap只在低峰期或 OOM 后分析 dump
- jcmd作为统一入口,尤其 VM.native_memory 排查堆外内存
- VisualVM用于本地或开发环境做性能分析
核心原则:生产环境首选无侵入工具(jstat/jstack/jcmd 非 live 操作),jmap 务必审批后执行。”
觉得对您有帮助,麻烦点点关注啦,您的关注是我创作的最大动力~ 🎯
