Jvm FullGC 如何排查?

我们有时在开发中会遇到FullGC的问题,排查的具体过程如下。

top命令查看cpu使用情况,获取对应的进程号pid:

top

如下所示,发现进程号pid为72的进程占用了近100%的cpu:
Jvm FullGC 如何排查?_Jvm FullGC

检查进程号的gc,是否发生fullGC:

下面这个命令的意思是每隔2s显示pid为72的进程的GC情况:

jstat -gcutil 72 2000

结果如下:
Jvm FullGC 如何排查?_Jvm FullGC_02

我们主要观察FGC这个参数,可以发现,每隔几秒,FGC的次数就会变多。

具体的含义如下:

参数含义:
S0 : Heap 上的 Survivor space 0 段已使用空间的百分比
S1 : Heap 上的 Survivor space 1 段已使用空间的百分比
E : Heap 上的 Eden space 段已使用空间的百分比
O : Heap 上的 Old space 段已使用空间的百分比
P : Perm space 已使用空间的百分比
YGC :从程序启动到采样时发生 Young GC 的次数
YGCT : Young GC 所用的时间 ( 单位秒 )
FGC :从程序启动到采样时发生 Full GC 的次数
FGCT : Full GC 所用的时间 ( 单位秒 )
GCT :用于垃圾回收的总时间 ( 单位秒 )

查看在这个进程中消耗cpu最多的线程

命令如下:

top -H -p 72

结果如下:
Jvm FullGC 如何排查?_Jvm FullGC_03

  • 将线程号80和79分别转换成16进制,将结果记下来,可以在后面的dump文件搜索。
printf %x 79

打印dump文件,分析线程堆栈

  • 根据进程号,输出进程的线程dump文件。

以下命令是将进程号为72的dump文件,输出到 /tmp/dump_file这个路径,也可以是其他任意路径。

jstack 72 > /tmp/dump_file
  • 打开dump文件,根据之前printf %x计算得到的16进制结果,搜索对应的线程号tid。
    就可以拿到线程的堆栈,找到出问题的代码了。

Jvm FullGC 如何排查?_Jvm FullGC_04