一次线上FullGC问题记录

​ 标题采自:英雄联盟-瑞文:断剑重铸之日,骑士归来之时!

断剑

​ 前两天早上在挤地铁的时候看到小组群里,主管发了好多消息,打开来一看,说是XX项目自从22号发版后,每天晚上就疯狂Full GC,让我们查一下什么原因,嘻嘻嘻,一开始听到,心里窃喜,为什么呢。因为自己以前对jvm也有些了解,不过都只是纸上谈兵罢了。现在刚好有机会,到公司就和小伙伴开始排查。以下是full gc的图片

​ 图 - 1.0


​ 图 - 2.0

​ 图 - 3.0

​ 当然这是运维给出来的,一开始看到这个,我是懵逼的,这tm是什么。接着往下看:运维又给出了如下图的dump日志

​ 图- 4.0

​ 我心里又问,这tm是什么。哇,一脸懵逼的我,又去补了jvm的内存模型。

重铸

​ 就在我补给的时候,有个大佬已经发言了,

​ 图 -5.0

​ 是不是感觉找到问题的来源了,就这有结束了,嘻嘻嘻。然后心里一阵窃喜,还好是老代码。不是我写的。但是事实却没有结束,为什么了。接着往下看:

​ 又一位大佬说:图-6.0 应该就是这块了

​ 图- 6.0

​ 主管又说:虽然是老代码,但是以前没发生过这样的问题,但是自从22号发版后就开始了,她就查看了一下22号有关AssostantsDto 这块有关的代码,并截图发了出来


​ 图-7.0

​ 看到发出来的这段,上面有我的署名 ouyangkang modify,我先是脸部发烫,然后大脑空白,接着回魂。我????? 写的。emmmm............。有点印象,这段代码有问题?看下绿色的那段我改的代码,

首先获取到一个list对象,遍历该list,给list容器中的对象赋值,并重新把该对象添加list容器中,乍看一下,没问题啊,这段代码。emm............................

仔细再看下绿色的那段我改的代码:

首先获取到一个list对象,遍历该list,给list容器中的对象赋值,并重新把该对象添加list容器中。等等,重新添加到list容器中,那么该list容器的大小不就也更大吗,那么又会进行一次循环,这不发生了死循环吗。哇!! 这就很有意思了,我的锅,我的锅。

那么怎么改呢:

第一种方案:直接去掉list.add(i,assistantsDto)。因为你堆list中的对象写入内容的话,list中的对象引用的地址是不会改变的。

第二种方案:list.set(i,assistantsDto) 将改dto替换。

项目重新发版,果然这几天xx项目再也没有出现频繁的Full GC了。

之日

图-2.0 解释

​ 解释断剑中图中含义:如果能够看懂前面几张图的这节就可以跳过了。图1.0就不解释了,首先图-2.0中第一行

60208.152(时间戳),[Full GC(Ergonomics)(解释:发生了什么GC)4035169K(解释:jvm堆中内存已用大小)->3635904(解释:经过full gc回收堆中内存后,堆中还剩余的内存大小) (4178944K(解释:jvm堆的总内存大小))]

从图-1.0 中可以看出,经过一个full gc后,堆中可用内存还是不多,并且发生了很多次full gc。我们都知道full gc就是stop the word 连续的full gc 。那么就导致这个项目不再对外提供服务了。

GC 策略

​ 大概说一下GC有哪几种回收策略,详情网上都有,自行查看,我就不写了(偷懒),算了,我还是写了点。

​ minor GC: 发生在年轻代。

​ 一开始:当eden区对象写满的时候,发生minor GC,把存活对象放到S0,释放其他对象所占内存,继续运行,eden区又写满了,发生minor GC,回收eden区和S0区存活对象,把存活对象防止S1,释放其他对象所占内存。eden区又写满了,发生minor GC,回收eden区和S1区存活对象,把存活对象防止S0,释放其他对象所占内存。反反复复,比较老一点的对象就放到了老年代。

​ major GC:发生在老年代:eg: 当发生minor GC 的时候,想把存活的老对象放到老年代,但是没有这么大的连续内存空间,此时就会发生major GC

​ full GC: 发生在年轻代和老年代 : eg: 当老年代和新生代内存都写的快满了的时候就会发生full GC|

JVM内存模型

​ 大概说一下JVM内存模型:下次写篇blog单独介绍一下吧 。先欠着

图-3.0 解释

​ 我截取部分进行解释:

S0C :Survivor0 可用内存大小 。 S1C: Survivor1可用内存大小

S0U:Survivor0 已用内存大小 S1U :Survivor1已用内存大小

EC: eden可用内存大小 EU:eden 已用内存大小

OC: 老年代可用内存大小 OU:老年代已用内存大小

MC:方法区可用内存大小 MU:方法区已用内存大小

CCSC :压缩类空间内存大小 CCSU:压缩类空间已用内存带下

YGC: 年轻代垃圾回收次数 YGCT:young GC消耗的时间

FGC:full GC 回收次数 FGC:full GC 消耗的时间

GCT : GC 消耗的时间

图-4.0 解释

​ 用mat工具打开jump文件所得到的,首先网上下载 mat,选择适合你电脑系统的。至于怎么操作,下次单独拎出来介绍。

其实我还研究了一点jvm虚拟机参数设置,GC日志打印,本地线程监控,我想留到下一篇博客再介绍吧。谢谢

如果我不写骑士归来之时,强迫症是不是会很难受。那么就推荐一下,留个言,我大声讲出来。

posted @ 2018-12-07 11:40  家里那只橘猫  阅读(1376)  评论(3编辑  收藏  举报