Linux 下 CPU 占用过高的排查过程

Linux 下 CPU 占用过高的排查过程

参考教程:线上CPU飙升100%问题排查,一篇足矣 - 只会一点java - 博客园

首先基本上可以确定,CPU 占用过高,大部分都是因为死循环,如果能直接看到死循环的地方就可以直接定位,但是大部分的时候因为代码的层层调用,直接找死循环代码是做不到的,那么我们就需要定位工具。

  1. 执行 top 命令:查看所有进程占系统 CPU 的排序,按 Shift+P 按 CPU 占用率进行倒叙排列。极大可能排第一个的就是咱们的 java 进程(COMMAND 列)。PID 那一列就是进程号。

    Shift+M 按内存占用率倒叙排列

  2. 执行 top -Hp 进程ID 命令:查看 java 进程下的所有线程占 CPU 的情况,再次按 Shift+P 按 CPU 占用率进行倒叙排列。找到占用最高的线程。

  3. 执行 echo "obase=16;<线程id>" | bc 命令 将占用最高的线程的 ID 转化为 16 进制,方便后续的对比和查找,top -Hp 进程号 命令的结果中 PID 列都是十进制的线程 ID,后续查看线程堆栈信息展示的都是十六进制,为了找到咱们的线程堆栈信息,咱们需要把线程号转成 16 进制。例如

  4. 执行 jstack 进程ID | grep -A 15 16进制线程ID (一般将字母小写) 查找某进程下 16 进制线程 ID(jstack 堆栈信息中的 nid)的线程状态。如下图

    第一个双引号圈起来的就是线程名,如果线程是 VM Thread 这就是虚拟机 GC 回收线程了,如果不是,通过调用栈基本上就能确定是哪一行代码。找下去应该就能找到死循环,

  5. 如果是 GC 线程,执行 jstat -gcutil 进程号 统计间隔毫秒 统计次数(缺省代表一直统计),查看某进程 GC 持续变化情况,如果发现返回中 FGC 很大且一直增大,则确认 Full GC! 也可以使用 jmap -heap 进程ID 查看一下进程的堆内从是不是要溢出了,特别是老年代内从使用情况一般是达到阈值 (具体看垃圾回收器和启动时配置的阈值) 就会进程 Full GC。

  6. 执行 jmap -dump:format=b,file=filename 进程ID,导出某进程下内存 heap 输出到文件中。可以通过 eclipse 的 mat 工具查看内存中有哪些对象比较多,飞机票:Eclipse Memory Analyzer(MAT),内存泄漏插件,安装使用一条龙