线上如何排查FullGC

发布于 2022-03-28  21.79k 次阅读


  • 首先查看Full GC花费的时间,比如2秒或以上,这种一般都需要尽快进行调优了
[root@localhost ~]# jstat -gcutil 5524 2000
  S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT   
 99.96   0.00  83.06  25.56  97.56  96.66      4    0.188     1    0.027    0.215
 99.96   0.00  83.06  25.56  97.56  96.66      4    0.188     1    0.027    0.215
 99.96   0.00  83.06  25.56  97.56  96.66      4    0.188     1    0.027    0.215
 99.96   0.00  83.06  25.56  97.56  96.66      4    0.188     1    0.027    0.215

S0:幸存区1占用率

S1:幸存区2占用率

E:Eden区占用率

O:老年区占用率

M:元数据区(java8,相当于java7及之前的永久代的概念)使用大小

ccs:压缩后使用率

YGC:young gc 次数,

YGCT:young gc耗时

FGC:full gc次数

FGCT:full gc耗时

GCt:GC共耗时

可以通过每次GC后 各区的占用率发生的变化来判断GC成果,

如果FULL GC频繁说明内存已经存在溢出可能或已经溢出,应用处理能力将会下降甚至停摆,因为大量时间在GC上面

如果YGC频繁,s0,s1,eden区使用率又没有明显下降,也需要注意,他们中的数据在增长到一定程度时,可能会进入old区,需要观察full gc情况

如果每次YGC后,但是s0,s1,eden区内存使用下降明显,一般不会有问题,说明jvm中存在了占比较重的短生命周期对象,能及时回收掉释放给其它请求或任务使用,只要保持获取与释放平衡就不会有太大问题

  • 堆dump来分析验证内存溢出的原因

堆dump是把内存情况按一定格式输出到文件,可用于检查Java 内存中的对象和数据情况。可使用JDK中内置的jmap命令创建堆dump文件。创建文件过程中,Java进程会中断,因此不要在正常运行时系统上做此操作。

  • 例如用内存分析工具JVisualVM分析内存分配情况
  • 一般我们的应用启动脚本里面会打印GC的日志,并且会提前设定阈值,在80%的可能就就会触发Gc了
  • 正常情况下,我们会优先看下云服务器的CPU、内存、磁盘等的状况,用下top命令
  • 借助arthas强大的工具分析

dashboard观察一下HTTP请求的qps, rt, 错误数, 线程池信息等等

thread -n 3查看当前最忙的前N个线程并打印堆栈

thread -b 查看线程死锁

jvm查看当前jvm信息

用trace命令分析方法内部调用路径,并输出方法路径上的每个节点上耗时

  • 通常CMS GC比Parallel GC要好,因为CMS GC的执行中并不会伴随内存压缩,因此GC速度会更快一些
  • 如果调整好参数后,需要做性能测试,然后连续观察几天

关于jvm调优的一些小tips:

  • 把Xms和Xmx设置为相同,这样可以减少GC后重新分配带来的性能开销
  • 把MaxPermSize和MinPermSize设置成一样(JDK8开始,没有了Perm,代替为元空间。元空间是直接存在内存中,不在JVM里面)