内存很空却频繁gc_堆内存占用很小 但是 JVM 频繁full gc 问题排查

最近碰到一个头疼的Full gc 问题,系统运行缓慢,但是使用 jstat -gcutil pid工具一看,堆内存占用不到10%,为啥会这样?

14121210defz.png

c18b220a6100e5dc0180848da9da978b.png

查看JVM配置如下 :

-Xms8G -Xmx8G -XX:NewRatio=4 XX:MaxPermSize=512m -Djava.awt.headless=true -XX:+UseCompressedOops -XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps

嗯?gc方式没有指定?

使用Jconsole连上去看下VM概要,看下gc方式是啥,年老代的Full gc 时间与次数都不正常:

垃圾收集器:  名称 = 'PS MarkSweep', 收集 = 56, 总花费时间 = 6.000 分

垃圾收集器:  名称 = 'PS Scavenge', 收集 = 47, 总花费时间 = 49.776 秒

竟然并行收集不靠谱,尝试使用并发收集,-XX:+UseConcMarkSweepGC -XX:+UseParNewGC

-XX:CMSFullGCsBeforeCompaction=5 -XX:+UseCMSCompactAtFullCollection

结果Full gc的更厉害了,平均一秒一次。

是什么问题导致了一直gc? 经过网上大神的指导,使用命令 jstat -J-Djstat.showUnsupported=true -snap [pid]  查看平均晋升空间,结果也不是这个问题,平均晋升空间远小于old区剩余空间呢。

后来经网友提醒, jstat -gccause pid 查看gc详细原因(一开始怎么没想到查看full gc原因,还是太嫩了,停留于表层的问题排查。)

2a3bd3036573701463a3fe67da273a66.png

发现程序中显示调用了 System.gc(),原因是程序中使用到了DirectorByteBuffer,使用了直接内存引用,程序每进行一次梳理,都进行一次 System.gc()的调用,以免发生OOM,但是调用也太频繁了,堆内存空间完全足够呢,就调用了System.gc()。

殊不知调用System.gc时,系统会建议执行Full GC,但是不必然执行,所以频繁发生了Full gc 问题。

调整程序,当堆内存不足的时候,才调用System.gc(),问题解决。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值