一、命令行工具(jdk 自带)
1.1 jps(java process status)
查看 java 进程。
jps -l # 显示完整类名 jps -v # 显示 jvm 参数 jps -m # 显示 main 方法参数 # 输出示例 12345 com.example.myapp 12346 org.apache.catalina.startup.bootstrap
1.2 jstat(jvm statistics monitoring tool)
监控 jvm 统计信息。
# 查看 gc 情况 jstat -gc <pid> 1000 10 # 每秒输出一次,共 10 次 # 输出字段 s0c/s1c # survivor 区容量 s0u/s1u # survivor 区使用量 ec/eu # eden 区容量/使用量 oc/ou # 老年代容量/使用量 mc/mu # 元空间容量/使用量 ygc/ygct # young gc 次数/时间 fgc/fgct # full gc 次数/时间 gct # 总 gc 时间 # 查看类加载 jstat -class <pid> # 查看编译 jstat -compiler <pid>
1.3 jinfo(configuration info)
查看和修改 jvm 配置。
# 查看所有参数 jinfo <pid> # 查看特定参数 jinfo -flag maxheapsize <pid> # 动态修改参数(部分参数支持) jinfo -flag +printgcdetails <pid>
1.4 jmap(memory map)
生成堆转储快照。
# 查看堆使用情况 jmap -heap <pid> # 查看对象分布 jmap -histo <pid> | head -20 # 生成 heap dump jmap -dump:format=b,file=heap.hprof <pid> # 生成时压缩 jmap -dump:live,format=b,file=heap.hprof <pid>
1.5 jstack(stack trace)
生成线程转储快照。
# 查看所有线程 jstack <pid> # 查找死锁 jstack <pid> | grep -a 20 "deadlock" # 导出到文件 jstack <pid> > thread_dump.txt # 查看 native 栈 jstack -m <pid>
线程状态:
runnable:运行中或可运行blocked:等待获取锁waiting:无限期等待(wait()/park())timed_waiting:限时等待(sleep()/wait(timeout))
1.6 jcmd(diagnostic command)
综合诊断工具(jdk 7+)。
# 列出所有诊断命令 jcmd <pid> help # 查看堆信息 jcmd <pid> gc.heap_info # 触发 gc jcmd <pid> gc.run # 生成 heap dump jcmd <pid> gc.heap_dump /path/to/heap.hprof # 查看线程 jcmd <pid> thread.print # 查看类加载 jcmd <pid> vm.class_hierarchy
二、可视化工具
2.1 jconsole
jdk 自带的图形化监控工具。
jconsole
功能:
- 内存监控(堆、非堆)
- 线程监控(死锁检测)
- 类加载监控
- mbean 管理
2.2 visualvm
更强大的图形化工具(jdk 8 内置,jdk 11+ 需单独下载)。
功能:
- 实时监控(cpu、内存、线程、类)
- 性能分析(cpu profiler、memory profiler)
- heap dump 分析
- thread dump 分析
- mbean 浏览器
2.3 mat(memory analyzer tool)
eclipse 提供的内存分析工具。
下载地址:www.eclipse.org/mat/
功能:
- 分析 heap dump
- 查找内存泄漏
- dominator tree(支配树)
- histogram(直方图)
- oql(对象查询语言)
使用步骤:
- 打开
.hprof文件 - 查看 leak suspects report(自动分析泄漏嫌疑)
- 使用 dominator tree 查找大对象
- 分析引用链,找到泄漏源头
2.4 arthas(阿里开源)
线上诊断神器。
下载地址:arthas.aliyun.com/
启动:
java -jar arthas-boot.jar
常用命令:
# 查看 dashboard
dashboard
# 监控方法调用
monitor com.example.myclass mymethod
# 追踪方法调用链路
trace com.example.myclass mymethod
# 查看方法参数和返回值
watch com.example.myclass mymethod '{params, returnobj}'
# 热更新代码
redefine /path/to/myclass.class
# 查看线程
thread
thread -b # 查找阻塞其他线程的线程
# 查看 jvm 信息
vmoption
sysprop
sysenv
三、常见故障排查
3.1 cpu 飙高
排查步骤:
# 1. 找到 cpu 高的 java 进程 top # 2. 查看进程中 cpu 高的线程 top -h -p <pid> # 3. 将线程 id 转换为 16 进制 printf "%x\n" <tid> # 4. 查看线程栈 jstack <pid> | grep <16进制tid> -a 20 # 5. 分析代码,找出死循环或频繁计算
3.2 内存泄漏
排查步骤:
# 1. 监控堆内存趋势 jstat -gc <pid> 1000 # 2. oom 时生成 heap dump -xx:+heapdumponoutofmemoryerror -xx:heapdumppath=/path/to/heap.hprof # 3. 手动生成 dump jmap -dump:live,format=b,file=heap.hprof <pid> # 4. 用 mat 分析 # - 查看 dominator tree # - 查找占用内存最多的对象 # - 分析引用链
3.3 死锁
排查步骤:
# 1. 生成线程转储 jstack <pid> > thread_dump.txt # 2. 查找死锁信息 grep -a 20 "deadlock" thread_dump.txt # 3. 或者用 jconsole / visualvm 的死锁检测功能 # 4. 分析持锁关系,修复代码
死锁示例输出:
found one java-level deadlock: ============================= "thread-1": waiting to lock monitor 0x00007f... (object 0x000000..., a java.lang.object), which is held by "thread-0" "thread-0": waiting to lock monitor 0x00007f... (object 0x000000..., a java.lang.object), which is held by "thread-1"
3.4 full gc 频繁
排查步骤:
# 1. 查看 gc 日志 jstat -gc <pid> 1000 # 2. 分析 gc 原因 # - 老年代满?→ 增大堆或优化对象生命周期 # - 元空间满?→ 增大 metaspace # - system.gc()?→ 检查代码或添加 -xx:+disableexplicitgc # 3. 生成 heap dump 分析 jmap -dump:live,format=b,file=heap.hprof <pid> # 4. 优化建议 # - 减少大对象创建 # - 对象池复用 # - 调整新生代大小
3.5 线程数过多
排查步骤:
# 1. 查看线程数 jstack <pid> | grep "java.lang.thread.state" | wc -l # 2. 查看线程详情 jstack <pid> > thread_dump.txt # 3. 分析线程类型 # - 业务线程过多?→ 检查线程池配置 # - waiting 线程过多?→ 检查是否有资源等待 # - blocked 线程过多?→ 检查锁竞争 # 4. 优化建议 # - 使用线程池 # - 减少锁粒度 # - 异步化处理
四、arthas 实战案例
4.1 定位慢方法
# 追踪方法执行时间
trace com.example.orderservice createorder
# 输出示例
`---ts=2024-01-01 12:00:00;thread_name=http-nio-8080-exec-1;id=1a;is_daemon=true;priority=5;
`---[0.523ms] com.example.orderservice:createorder()
+---[0.012ms] validateorder()
+---[0.456ms] savetodatabase() ← 慢
`---[0.055ms] sendnotification()
4.2 查看方法入参和返回值
# 监控方法调用
watch com.example.userservice getuser '{params, returnobj}' -x 2
# 输出示例
method=com.example.userservice.getuser location=atexit
ts=2024-01-01 12:00:00; [cost=0.234ms]
param[0]=12345
return=@user[id=12345,name=alice,email=alice@example.com]
4.3 热更新代码(紧急修复 bug)
# 1. 编译新代码 javac -cp app.jar myclass.java # 2. 上传到服务器 # 3. 热更新 redefine /path/to/myclass.class # 4. 验证
注意:只能修改方法体,不能修改方法签名、字段、继承关系。
4.4 查看系统属性
# 查看 jvm 参数 vmoption # 查看系统属性 sysprop # 查看环境变量 sysenv
五、面试题精选
q1:如何排查 cpu 飙高问题?
top找到 cpu 高的进程top -h -p <pid>找到 cpu 高的线程printf "%x"转换线程 id 为 16 进制jstack查看线程栈- 分析代码,找出死循环或频繁计算
q2:如何排查内存泄漏?
- 监控堆内存趋势(持续增长)
- oom 时生成 heap dump
- 用 mat 分析,查找大对象和引用链
- 定位泄漏代码,修复
q3:jstack 和 jmap 的区别?
jstack:生成线程转储,查看线程状态、死锁jmap:生成堆转储,查看对象分布、内存泄漏
q4:什么是 heap dump 和 thread dump?
- heap dump:堆内存快照,包含所有对象信息,用于分析内存泄漏
- thread dump:线程快照,包含所有线程状态和栈信息,用于分析死锁、cpu 高
q5:arthas 的优势是什么?
- 无需重启应用
- 支持线上诊断
- 功能强大(监控、追踪、热更新)
- 非侵入式
q6:full gc 频繁怎么排查?
- 查看 gc 日志,确认 gc 原因
- 生成 heap dump 分析
- 检查是否有内存泄漏
- 调整堆大小或 gc 参数
- 优化代码,减少对象创建
q7:如何预防死锁?
- 固定锁顺序
- 使用
trylock超时 - 减少锁粒度
- 使用
jstack定期检测
q8:生产环境如何监控 jvm?
- 命令行工具:
jstat、jmap、jstack - 可视化工具:visualvm、mat
- apm 工具:arthas、skywalking、pinpoint
- 日志监控:gc 日志、应用日志
- 指标监控:prometheus + grafana
以上就是jvm性能调优必备之监控与故障排查工具使用教学的详细内容,更多关于jvm监控与故障排查工具的资料请关注代码网其它相关文章!
发表评论