这种问题,一般开发人员还是很难遇到,或者说是遇到了也会交给大牛去处理,所以这里我们就自己模拟场景,然后去排查解决。当然实际生产情况查询原因更难,有很多复杂的情况。
话不多说,首先是编写触发的代码
/**
* @author 594781919@qq.com
* @date 2020/6/8
**/
public class CpuTest {
public static void main(String[] args) {
while (true) {
/* */
}
}
}
然后我们执行代码
在这里我是在 centos 系统执行的代码,这样更加贴近于实际生产情况。
$ java CpuTest
现在,我们开始排查
1)执行 top
命令,查看服务器的 cpu 情况
从下图中,我们可以看到有一个 java 执行的命令,占用了 98% 的 CPU。
2)执行 top -Hp [PID]
,查看线程情况
参数说明:
- p:指定特定的 pid 进程号进行观察。
- H:查看由某个进程启动的所有线程
这里我们执行命令top -Hp 10237
,可以看到 PID 为 10238 的线程占用了 98% 的 CPU 资源。
3)执行jstack [进程 ID]
,查看 JVM 栈的情况
这里我们有两种执行方式: - 第一种,将 JVM 栈的情况存到一个文件中,然后阅读文件进行排查。
$ jstack 10237 >> stack.log
在当前目录就会生成一个 stack.log
文件
然后我们打开 stack.log
文件,找到占用 CPU 资源的线程的栈信息。
这里注意,线程 ID 是以 16 进制来显示的,所以我们需要把刚才查出来的线程 ID 转为 16 进制。
[root@jamie java]# printf '%x\n' 10238
27fe
- 第 2 种,执行查看占用 CPU 资源的线程的栈情况。
$ jstack 10237 | grep 27fe -A 30
参数说明:
10237:进程ID
27fe:线程ID
-A 30:显示匹配行和它后面的 30 行。(这里顺便说下,-B 是显示匹配行和它前面的n行。
-C 是匹配行和它前后各n行。)
这样,我们的排查工作就完结了。