1.top

通过top命令,进入界面之后按P,根据CPU占用排序,找到最耗CPU的进行PID,从下图种可以发现PID为 15913。可以看到是java应用占用CPU。
image-1648569609378

2.top -p 15913 -H

加上 -H 选项可以该进程的相关线程信息,从下图种可知最耗CPU的两个线程PID分别是 15924和15925。
执行printf "%x\n" 15924,得到对应的16进制为 0x3e34和0x3e35。
image-1648569737512

3.jstack堆栈跟踪

jstack 15913 > jstack.log

jstack命令可以得到线程堆栈信息,根据这些线程堆栈信息,可以去检查Java程序出现的问题,如检测死锁。

在日志的最后面找到了0x3e34和0x3e35,对应的是GC线程,由此猜想可能是不停的GC导致CPU占用过高。

也可以直接在终端搜索对应线程的上下文日志

jstack 15913 |grep -A 30 0x3e34

4.jstat虚拟机统计信息

jstat -gcutil 15193 1000 20

以上命令代码每过一秒打印一次gc情况,打印20次
image-1648570044481

S0:S0使用率;
S1:S1使用率;
E:Eden使用率;
O:老年代使用率;
P:PermGen的内存使用百分比;
M:MetaSpace的内存使用百分比;
YGC:Minor GC总共次数;
YGCT:Minor GC总共耗时,单位s;
FGC:Full GC总共次数;
FGCT:Full GC总共耗时,单位s;

由上图可知,20s内发生了13次Full GC,所以问题就是Full GC太频繁导致的,内存使用率太高,猜测可能是因为为JVM分配的内存太小了。

5.使用jmap查看内存情况

jmap -heap 15193

image-1648570126987
最大内存为948MB,老年代632MB,使用率已经无线接近100%。机器有4G内存,但为该进程分配的JVM最大内存只有948MB。

6.使用jmap -dump生成堆转储快照

jmap -dump:format=b,file==heap.hprof 15193

以上命令用于生成堆转储快照。可以使用jhat进行快照分析。

7.可视化分析工具

  1. Jconsole:Java监视与管理控制台。可以实现内存监控,线程监控等。
  2. VisualVM:多合一故障处理工具。可以用来显示虚拟机进程信息;应用程序的处理器,垃圾回收,堆,方法区以及线程信息;dump以及分析堆转储快照;方法级程序运行性能分析,找到调用最多,耗时最长的方法;离线程序快照等。
  3. Java Mission Control:在线监控工具。

CPU占用100%排查过程