排查 CPU 100% 的 Java 程序

这种问题,一般开发人员还是很难遇到,或者说是遇到了也会交给很厉害的人去处理,所以这里我们就自己模拟场景,然后去排查解决。当然实际生产情况查询原因更难,有很多复杂的情况。

话不多说,首先是编写触发的代码
/**
 * @author [email protected]
 * @date 2020/6/8
 **/
public class CpuTest {
    public static void main(String[] args) {
        while (true) {
            /* */
        }
    }
}
然后我们执行代码

在这里我是在 centos 系统执行的代码,这样更加贴近于实际生产情况。

$ java CpuTest
现在,我们开始排查

1)执行 top命令,查看服务器的 cpu 情况
从下图中,我们可以看到有一个 java 执行的命令,占用了 98% 的 CPU。
排查 CPU 100% 的 Java 程序_第1张图片
2)执行 top -Hp [PID],查看线程情况
参数说明:

  • p:指定特定的 pid 进程号进行观察。
  • H:查看由某个进程启动的所有线程
    这里我们执行命令top -Hp 10237,可以看到 PID 为 10238 的线程占用了 98% 的 CPU 资源。
    排查 CPU 100% 的 Java 程序_第2张图片
    3)执行 jstack [进程 ID],查看 JVM 栈的情况
    这里我们有两种执行方式:
  • 第一种,将 JVM 栈的情况存到一个文件中,然后阅读文件进行排查。
$ jstack 10237 >> stack.log

在当前目录就会生成一个 stack.log 文件
排查 CPU 100% 的 Java 程序_第3张图片
然后我们打开 stack.log文件,找到占用 CPU 资源的线程的栈信息。
这里注意,线程 ID 是以 16 进制来显示的,所以我们需要把刚才查出来的线程 ID 转为 16 进制。

[root@jamie java]# printf '%x\n' 10238
27fe

排查 CPU 100% 的 Java 程序_第4张图片

  • 第 2 种,执行查看占用 CPU 资源的线程的栈情况。
$ jstack 10237 | grep 27fe -A 30

参数说明:
10237:进程ID
27fe:线程ID
-A 30:显示匹配行和它后面的 30 行。(这里顺便说下,-B 是显示匹配行和它前面的n行。
-C 是匹配行和它前后各n行。)
排查 CPU 100% 的 Java 程序_第5张图片
这样,我们的排查工作就完结了。

你可能感兴趣的:(Java)