记一次频繁FGC的简单排查

作者: 美团Java | 来源:发表于2017-04-16 09:26 被阅读5026次

    简书 占小狼
    转载请注明原创出处,谢谢!
    如果读完觉得有收获的话,欢迎点赞加关注

    周末愉快,今天有时间记录一下上周遇到的一个问题,学习的脚步不能放慢,也不敢放慢。

    存在问题

    在线上环境进行服务压测,压测完成后,cpu使用率居高不下,很是费解,按理说已经没有压测请求了,这时消耗cpu资源的只有GC线程了,可以通过jstat命令查看一下JVM的GC情况,然后就碰到了诡异的GC问题。

    jstat命令

    jstat [ generalOption | outputOptions vmid [interval[s|ms] [count]] ]

    参数:
    generalOption: 一般使用-gcutil查看GC情况
    vmid: 虚拟机进程号,即当前运行的java进程号
    interval: 间隔时间,单位为秒或毫秒
    count: 打印次数,如果缺省则打印无数次

    执行jstat -gcutil 9132 1000命令,线上服务器的GC情况如下:

    参数说明如下:
    S0: 新生代中Survivor space 0区已使用空间的百分比
    S1: 新生代中Survivor space 1区已使用空间的百分比
    E: 新生代已使用空间的百分比
    O: 老年代已使用空间的百分比
    P: 永久带已使用空间的百分比
    YGC: 从应用程序启动到当前,发生Yang GC 的次数
    YGCT: 从应用程序启动到当前,Yang GC所用的时间【单位秒】
    FGC: 从应用程序启动到当前,发生Full GC的次数
    FGCT: 从应用程序启动到当前,Full GC所用的时间
    GCT: 从应用程序启动到当前,用于垃圾回收的总时间【单位秒】

    问题分析

    通过打印的GC数据可以看出,JVM一直在进行FGC(cms gc),不过老年代的使用率反而没有下降,一直稳定在60.16%,对这一情况很疑惑,几乎每次都重现,后来去仔细查看了JVM的启动参数,发现其中CMSInitiatingOcupancyFraction参数,被设置成60,意味着当老年代的使用率达到阈值60%时会触发FGC,但是FGC之后,老年代的使用率还是大于60%,所以会不断的进行FGC,建议这个值不要设置的这么小。

    至于为什么FGC之后,老年代的使用率没有下降,可以通过dump查看到底是哪些存活对象在作怪,在进行FGC时,通常会伴随着一次YGC,但这也不是一定的,如果执行YGC之后没有明显效果的话,会设置一个变量,表明下次不用进行YGC,所以如果老年代如果存在大量对象的GC ROOT在新生代的话,这些对象就不会被回收,这种情况必须强制执行一次YGC之后,才有可能回收这些老年代的对象,比如添加参数-XX:+CMSScavengeBeforeRemark,就可以解这个问题。

    昨天正好笨神也遇到类似的问题,并写一篇文章《又抓了一个导致频繁GC的鬼--数组动态扩容》进行分析,可以参考一下。

    相关文章

      网友评论

      • hongrm:大牛就是叼,深入浅出!向你们看齐!
      • SomeHow_8c69:之前我们碰到一个问题,现象也是这样,最终定位是list的扩容导致的
        美团Java:@SomeHow_8c69 :+1:
      • 哈利波特与编译原理:你好,节日快乐,我想问个问题,能不能告诉我concurrenthashmap的链表长度为什么是到了8才转换红黑树而不是别的数,还有synchronized和lock分别在什么场景下是最优使用,谢谢
      • a9f0f91b91fd:狼哥,上周六去一家公司面试,基本都过了,当时就是谈薪水的问题,让我发邮件告知当前薪水和期望薪水,然后说发过邮件下周联系我,但是到现在也没有联系我,我感觉自己成为备胎了,备胎,备胎。。。。。。
        美团Java:@蜗牛加速飞 首先公司招聘肯定是招性价比最高的员工,这个情况没办法改变,你能做的就是好好准备,再多面试几家公司,让offer成为备胎啊:joy:
        a9f0f91b91fd:这个公司这周应该还在面试招人,我觉得他们如果找到更合适的就不要我了,我该怎么办
      • d8ced77a0050:你工作的时间并不是很长,但是感觉你的技术水平很厉害,我感觉周围大部分程序员的进步还是很慢的,一方面可能是自己平时没有钻研,另外一方面是工作的内容也也不会涉及到这么深入的技术,您是怎么快速提升自己的技术水平的
      • 90bb5aacf3ff:笨神又发了篇补充说明的哦
        博主加油,贵在坚持 做好一件事不容易
        美团Java:@䒕愺 哈哈,笨神最近高产
      • 彭小位:狼大,我决定花些时间好好看看你的博客,学习,沉淀。你可以支持我一下吗🤓
        zoterap:@占小狼 可以从后面支持
        彭小位: @占小狼 哈哈哈🐒
        美团Java:@帕布里可 可以
      • sleeeeeeeep:小狼你好,你的博客我都一一看过了。有些写的确实很好。我有个问题,请不吝赐教。你读过书以后除了写博客,写demo,有没有其他方法加深印象,使其真正称为自己的知识。而不是看过就会,会了就忘,恶性循环。
        美团Java:@sleeeeeeeep 需要反复看,加深印象
      • wyn_做自己:两篇文章都看过了,受教了,我想问一下,你们这是工作场景都能遇到,像我工作场景不能遇到,看jvm
        那本书的时候,貌似挺多都看懂了,但是过一段时间就忘记了,这种情况能给点好的建议吗?
        美团Java:@wyn_做自己 哈哈,是不是觉得有难度了啊
        wyn_做自己:@占小狼 都说看源码是大牛必经之路,说实话,真是看不进去。什么时候还能再总结些面试题啊?你上次分享的面试题真的感觉不是一个层次的:sweat:
        美团Java:@wyn_做自己 多看就能记住啦,加深理解,适当可以看看源码
      • 贺小五:昨天刚好看到你发的笨神连接,你就写了一篇
        美团Java:@贺小五 因为正好也遇到了这个问题,但是没有笨神的深入,哈哈
      • 5fa1243ea3a3:你好,“老年代如果存在大量对象的GC ROOT在新生代”,能帮我解释下这句详细是什么吗,水平有限,如果问的问题太初级请见谅:blush:
        5fa1243ea3a3:@cbe8f18806e3 明白了,之前不明白GC ROOT 是什么意思,看了下可达性分析算法之后有看到这个词,就明白了,谢谢!
        cbe8f18806e3:@空白符 这个词来源是对象可达性,垃圾回收中判断一个对象是否可以被回收,就是看它的可达性
        美团Java:@空白符 垃圾回收算法中活跃对象的标记过程是根据gc root确定的,一般作为gc root的对象为静态变量,栈中的引用,系统字典的引用等等

      本文标题:记一次频繁FGC的简单排查

      本文链接:https://www.haomeiwen.com/subject/xvhvottx.html