Java进程CPU占用率过高分析定位
编辑
848
2022-08-19
一、场景描述
在实际应用场景中,JAVA 进程导致宿主机 CPU 使用率高的情况很常见,可能导致的原因很多:主机配置过低、代码质量低等;通常处于 bug 修复或者性能优化的需求,需要定位耗费大量 CPU 时间的罪魁祸首,这里提供几种常见的定位排查手段。
二、可选排查方式
【方式一】命令行 + jstack
jstack 是 Java 进程内的线程堆栈信息的常用工具,具体使用如下:
- 定位消耗 CPU 的进程 pid(按 P 排序):
top -c
- 可以将进程堆栈导出:
jstack -l <pid> > jstack.txt
,然后加载到本地客户端工具或者网页工具(如:heapdump)中进行分析 - 也可以完全使用命令行分析,定位消耗 CPU 的具体线程及其堆栈:
top -Hp <pid>
;输入 P 按 CPU 使用率排序,记住线程 pid 并转化为 16 进制:printf ‘%x\n’,得到 16 进制的 nid-16;接着在 jstack 中找到对应堆栈信息: jstack -l <pid> | grep <nid-16> -C5 -color
或者jstack -l <pid> | grep <nid-16>
- 检查 JAVA 进程是否存在死锁:
jstack -l -F <pid>
【方式二】Arthas
Arthas 是 Alibaba 开源的一个 Java 诊断工具,方便进行问题的定位和诊断,可以在线排查问题,无需重启;动态跟踪 Java 代码;实时监控 JVM 状态。
- 下载 jar 包:
curl -O https://alibaba.github.io/arthas/arthas-boot.jar
- 使用和业务应用相同的用户运行调试命令(会进入专用控制台并自动识别 java 进程并提供序号列表供选择):
java -jar arthas-boot.jar
- 使用说明:
- 输入help命令查看支持的选项,dashboard命令用于整体展示进程所有线程、内存、GC 等情况,通过thread的-n 5选项找出最忙的前 5 个线程、-b 选项找出阻塞其他线程的线程,再输入thread
查看详情,使用trace或者tt命令进行跟踪分析,输入stop退出。 - profiler命令支持生成应用热点的火焰图,默认生成的是 cpu 的火焰图(即 event 为 cpu,可以用 –event 参数来指定,支持的 event 可以使用profiler list命令获取), 常规命令:
启动采样:profiler start
查看已获取的样本数:profiler getSamples
查看采样状态:profiler status
停止采样:profiler stop
(支持通过–file指定保存的文件名、–format html指定输出为 html 格式,默认为 svg)
- 输入help命令查看支持的选项,dashboard命令用于整体展示进程所有线程、内存、GC 等情况,通过thread的-n 5选项找出最忙的前 5 个线程、-b 选项找出阻塞其他线程的线程,再输入thread
- 火焰图分析说明:
y 轴表示调用栈,每一层都是一个函数。调用栈越深,火焰就越高,顶部就是正在执行的函数,下方都是它的父函数
x 轴表示抽样数,如果一个函数在 x 轴占据的宽度越宽,就表示它被抽到的次数多、即执行的时间长。注意,x 轴不代表时间,而是所有的调用栈合并后,按字母顺序排列的
颜色没有特殊含义,因为火焰图表示的是 CPU 的繁忙程度,所以一般选择暖色调
火焰图就是看顶层的哪个函数占据的宽度最大。只要有”平顶”(plateaus),就表示该函数可能存在性能问题
【方式三】show-busy-java-threads 脚本
下载安装包:wget --no-check-certificate https://github.com/oldratlee/useful-scripts/archive/release.zip
解压:unzip release.zip && cd useful-scripts-release
使用(找出指定 java 进程中最消耗 CPU 的线程(缺省 5 个),打印出其线程栈):./show-busy-java-threads -p <pid>
- 5
- 0
-
分享