最近碰到一个头疼的Full gc 问题,系统运行缓慢,但是使用 jstat -gcutil pid工具一看,堆内存占用不到10%,为啥会这样?
查看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 时间与次数都不正常:
|
结果Full gc的更厉害了,平均一秒一次。
是什么问题导致了一直gc? 经过网上大神的指导,使用命令 jstat -J-Djstat.showUnsupported=true -snap [pid] 查看平均晋升空间,结果也不是这个问题,平均晋升空间远小于old区剩余空间呢。
发现程序中显示调用了 System.gc(),原因是程序中使用到了DirectorByteBuffer,使用了直接内存引用,程序每进行一次梳理,都进行一次 System.gc()的调用,以免发生OOM,但是调用也太频繁了,堆内存空间完全足够呢,就调用了System.gc()。
殊不知调用System.gc时,系统会建议执行Full GC,但是不必然执行,所以频繁发生了Full gc 问题。
调整程序,当堆内存不足的时候,才调用System.gc(),问题解决。