Linux 下 CPU 占用过高的排查过程
Linux 下 CPU 占用过高的排查过程
参考教程:线上CPU飙升100%问题排查,一篇足矣 - 只会一点java - 博客园
首先基本上可以确定,CPU 占用过高,大部分都是因为死循环,如果能直接看到死循环的地方就可以直接定位,但是大部分的时候因为代码的层层调用,直接找死循环代码是做不到的,那么我们就需要定位工具。
-
执行
top
命令:查看所有进程占系统 CPU 的排序,按Shift+P
按 CPU 占用率进行倒叙排列。极大可能排第一个的就是咱们的 java 进程(COMMAND 列)。PID 那一列就是进程号。按
Shift+M
按内存占用率倒叙排列 -
执行
top -Hp 进程ID
命令:查看 java 进程下的所有线程占 CPU 的情况,再次按Shift+P
按 CPU 占用率进行倒叙排列。找到占用最高的线程。
-
执行
echo "obase=16;<线程id>" | bc
命令 将占用最高的线程的 ID 转化为 16 进制,方便后续的对比和查找,top -Hp 进程号
命令的结果中 PID 列都是十进制的线程 ID,后续查看线程堆栈信息展示的都是十六进制,为了找到咱们的线程堆栈信息,咱们需要把线程号转成 16 进制。例如 -
执行
jstack 进程ID | grep -A 15 16进制线程ID
(一般将字母小写) 查找某进程下 16 进制线程 ID(jstack
堆栈信息中的 nid)的线程状态。如下图第一个双引号圈起来的就是线程名,如果线程是
VM Thread
这就是虚拟机 GC 回收线程了,如果不是,通过调用栈基本上就能确定是哪一行代码。找下去应该就能找到死循环, -
如果是 GC 线程,执行
jstat -gcutil 进程号 统计间隔毫秒 统计次数(缺省代表一直统计)
,查看某进程 GC 持续变化情况,如果发现返回中 FGC 很大且一直增大,则确认 Full GC! 也可以使用jmap -heap 进程ID
查看一下进程的堆内从是不是要溢出了,特别是老年代内从使用情况一般是达到阈值 (具体看垃圾回收器和启动时配置的阈值) 就会进程 Full GC。 -
执行
jmap -dump:format=b,file=filename 进程ID
,导出某进程下内存 heap 输出到文件中。可以通过 eclipse 的 mat 工具查看内存中有哪些对象比较多,飞机票:Eclipse Memory Analyzer(MAT),内存泄漏插件,安装使用一条龙;