概述
当Java程序的CPU使用率达到100%的情况,可能是代码中存在死循环、频繁的I/O操作、不合理的锁(CAS)等问题导致。
排查问题的思路是先通过Linux命令top查看进程和线程的ID,然后把线程ID转换成16进制,最后通过java的工具jstack把栈信息打印出来,拿着16进制的线程ID找到具体的线程代码这样就能定位到具体导致cpu100%的代码了。
java程序通过docker运行,下面的命令都是基于这种环境,如果是直接部署的原理是一样的,并且下面的都是例子并不是cpu是100%
占用cpu的Java进程
如何通过top命令找到占用cpu最高的线程ID?
- 通过
top
找到java程序的进程ID是24:docker exec -it nacos top
- 通过进程ID(24)找到进程中消耗cpu最高的线程ID(100):
docker exec -it nacos top -H -p 24
现在我们假如的java程序24对应的100号线程导致了cpu过高。
把线程号对应的16进制找到
使用命令printf:docker exec -it nacos printf "0x%x\n" 100
得到结果是0x64(因为jstack中的nid信息是有0x开头的所以我们直接加上了这个0x。
root@debian:~# docker exec -it nacos printf "0x%x\n" 100
0x64
最后通过jstack找到具体的进程所在的代码
注意jstack的时候参数是java主线程的ID,这样可以把所有的线程信息输出出来。
docker exec -it nacos jstack 24 | grep -C 10 0x64
// grep -C 10 是显示0x64所在行的上下10行
建议
Java程序中的每个线程最好都要创建线程名称,这样的话可以不通过jstack直接看到线程名字,这样在代码中可以直接找到对应的代码。