本人自己在云服务器上部署了个应用,都要忘了这么回事了,突然打开发现特别卡顿,
数据量并不多,内存也是够用的,访问量也并不高,就时快时慢的问题
以下是机器配置以及统计到的数据
机器配置:2核4G
JVM内存大小:2G
系统运行时间:7天
期间发生的FullGC次数和耗时:500多次,200多秒
期间发生的YoungGC次数和耗时:1万多次,500多秒
大致算下来每天会发生70多次FullGC,平均每小时3次,每次FullGC在400毫秒左右;每天会发生1000多次YoungGC,每分钟会发生1次,每次YoungGC在50毫秒左右。
以下是jvm设置参数
-Xms1536M
‐Xmx1536M
‐Xmn512M
‐Xss256K
‐XX:SurvivorRatio=6
‐XX:MetaspaceSize=256M
‐XX:MaxMetaspaceSize=256M
2
‐XX:+UseParNewGC
‐XX:+UseConcMarkSweepGC
‐XX:CMSInitiatingOccupancyFraction=75
‐XX:+UseCMSInitiatingOccupancyOnly
经过分析感觉可能会由于对象动态年龄判断机制导致fullgc较为频繁,说明年轻代空间太小,需要大量的对象挪到老年代,所以增加了年轻代的空间,调整后如下
-Xms1536M
‐Xmx1536M
‐Xmn1024M
‐Xss256K
‐XX:SurvivorRatio=6
‐XX:MetaspaceSize=256M
‐XX:MaxMetaspaceSize=256M
2
‐XX:+UseParNewGC
‐XX:+UseConcMarkSweepGC
‐XX:CMSInitiatingOccupancyFraction=92
‐XX:+UseCMSInitiatingOccupancyOnly
是不是以为优化完结束了,不,你错了,完全没有好转,反而根据监控显示,更加严重
这个时候,就又继续尝试,full gc太多的原因大概分为两种,
1:手动调用System.gc()
2:元空间不够,也就是方法区
然后我继续做了相应调整 使用-XX:+DisableExplicitGC,这个是禁用手动GC的,设置了以后你手动gc也没用,顺便增加了元空间的大小
不出所料,并没有什么用,并且得到了一个重要信息,看到大量的对象从年轻代移动到老年代,这个时候我用jmap命令查到了这个对象是user,然后继续用jvisualvm来定位到了代码,是一个用户导入的功能,然后对功能做了相应的优化,分批导入