【大白话说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.1 jps:定位目标进程

bash 复制代码
jps -l          # 显示完整主类名
jps -v          # 显示传递给 JVM 的参数

场景:启动分析前第一步,拿到 PID。


2.2 jstat:实时监控 GC(最常用)

bash 复制代码
# 每1秒打印一次,共打印10次
jstat -gcutil <PID> 1000 10

# 输出列解读:
# 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.3 jmap:堆内存快照(谨慎使用)

bash 复制代码
# 生成 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.4 jstack:线程快照(无痛)

bash 复制代码
# 导出线程栈
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.5 jinfo:查看运行时参数

bash 复制代码
# 查看所有可设置参数及当前值
jinfo -flags <PID>

# 查看单个参数
jinfo -flag UseG1GC <PID>

# 动态修改(部分参数支持)
jinfo -flag +HeapDumpOnOutOfMemoryError <PID>

场景 :线上验证 -Xmx 是否生效、某个 GC 参数是否真的被打开。


2.6 jcmd:新一代瑞士军刀(JDK 7+ 推荐)

bash 复制代码
# 列出所有可执行命令
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 dump
jcmd <PID> GC.heap_dump /tmp/dump.hprof

# 查看 Native 内存(诊断直接内存/堆外)
jcmd <PID> VM.native_memory summary

优势:统一入口,输出结构更清晰,部分操作比 jmap 更安全。


2.7 VisualVM:图形化利器

连接方式

  • 本地:自动检测本机 Java 进程
  • 远程 :通过 JMX(需开启 -Dcom.sun.management.jmxremote

常用 Tab

  • Monitor:CPU/堆/元空间/类/线程 实时曲线
  • Threads:线程状态及堆栈,可检测死锁
  • Sampler:CPU 采样 → 热点方法;内存采样 → 对象分配统计
  • Profiler(需插件):更精确但开销大,生产慎用

生产远程连接示例(JMX 参数):

bash 复制代码
-Dcom.sun.management.jmxremote=true \
-Dcom.sun.management.jmxremote.port=9999 \
-Dcom.sun.management.jmxremote.authenticate=false \
-Dcom.sun.management.jmxremote.ssl=false

3. 实战案例:生产 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`
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 看趋势或 Arthas heapdump

Q2:jstack 打印出的 BLOCKED 线程很多,一定有问题吗?

A:不一定。若 BLOCKED 是瞬时锁竞争且正常情况(如 synchronized 高并发),只要不持续堆积就正常。需多次打印确认是否一直卡在同一锁

Q3:远程连接 VisualVM 不安全怎么办?

A:生产禁止明文 JMX。替代方案:

  • jstat / jstack 本地执行后导出分析
  • 用 Arthas(阿里开源)隧道连接
  • 开启 JMX + SSL 认证(复杂)

Q4:jcmd 能完全替代 jmap 吗?

A:大部分可以。jcmd GC.heap_dumpjmap -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 务必审批后执行。"


觉得对您有帮助,麻烦 点点关注啦 ,您的关注是我创作的最大动力~ 🎯

相关推荐
梅菲塔亚5 小时前
Keepalived高可用全解析
linux·运维·服务器·开发语言·网络·php
依然鸣5 小时前
PTA团体程序设计天梯赛L2真题讲解L2-005-008
开发语言·数据结构·c++·算法·深度优先·pat考试·图论
.柒宇.6 小时前
运维常见面试题_04_Nginx与DNS服务
运维·nginx·面试·dns
君顾16 小时前
代驾跑腿业务系统实战开发指南
java·开发语言·代驾跑腿
夏幻灵6 小时前
从语法坑点到 JS 内存底层:Vue 3 watch 侦听器深度全解
开发语言·javascript·vue.js
NGINX开源社区7 小时前
NGINX Ingress Controller 5.5:安全性与性能提升,迁移更轻松
java·服务器·nginx
k4m7v2pz7 小时前
Rust 长跑守护进程日志治理:切分、时区与结构化
开发语言·后端·rust·日志系统·日志轮转·ndjson
FfHUCisI7 小时前
Golang RESTful API 设计原则
开发语言·golang·restful
breeze jiang7 小时前
ESLint flat config 配置实战:五大字段、规则严重级别与 --fix 能力边界详解
开发语言·前端·javascript
云烟成雨TD7 小时前
Micrometer 系列【25】Spring Boot Actuator | Spring MVC、Spring WebFlux 指标
java·spring boot·micrometer