JVM调优案例

案例1(xmx与xms不一致导致的问题)

某天项目机器进行迁移后频繁发生FullGC报警,查询内存信息和启动参数

启动参数:-XX:MetaspaceSize=128M;   -Xmx4096M -Xms512M -Xss256k -XX:+UseConcMarkSweepGC -XX:+UseParNewGC

内存信息如图1

 

 

(图1:JVM总内存) 

  FullGC次数监控如图2

 

 

 (图2:FullGC次数)

  查看内存和GC现象,可以发现以下问题

      最大堆内存配置为 -Xmx4096M,但是图1所示,总内存还未达到1000M已经发生FullGC,JVM配置的最大内存一直未生效。

  原因是-Xmx4096M -Xms512M中配置的最小堆内存和最大堆内存不一致,当JVM的当前堆内存已经堆满之后会先触发FullGC,如果FullGC之后内存依然不足,则会触发堆自动扩容,然而该应用每次FullGC之后都有大量内存被回收,JVM的空间暂时能够满足应用使用,因此不会进行扩容。对该现象进行复现,将垃圾回收器修改为JAVA8 默认的垃圾回收器组合(parallel scavenge + parallel old)时,不会进行FullGC,而是直接完成扩容,而使用CMS+ParNew的组合则会发生FullGC。因此判断先进行FullGC 再进行扩容,应该与垃圾回收器有关。当然本次调优的重点还是将最小堆内存和最大堆内存保持一致。寄防止内存不足发生FullGC,也防止向系统申请内存浪费时间。  

 -Xmx4096M -Xms4096M

  

 

                案例2(年轻代不足)

  某天线上突然有个服务发生了短暂的超时,查看监控,发现机器发生了FullGC导致STW。 查看内存监控,发现该机器老年代内存量一直缓慢增长,增长到了上限之后,就发生FullGC(图已经丢了)。查看JVM的启动参数的关键配置如下:

-Xms3600m -Xmx3600m -XX:MetaspaceSize=512m -XX:MaxMetaspaceSize=512m

      因为面向用户的服务还是期望STW的时间短暂或者永远不要出现FullGC,因此调整JVM参数

 -Xms4g -Xmx4g -Xmn2g -XX:SurvivorRatio=4 

      堆内存改为4G保持和其他项目统一,默认情况下年轻代/老年代比例为1:2,堆为4G时,默认年轻代大小为4/3G ,将年轻代调整为2G,增加年轻代的大小,是防止当QPS较高的时候,年轻带可能存在来不及回收的情况,导致新生成的对象时内存不足,导致不足龄的年轻代对象直接进入老年代。默认情况下eden区和survivor区的比例为8:1:1,调整比例为4:1:1,可以理解为增大S0、S1,减小Eden区。根据之前的判断,年轻带无法快速清空,导致部分对象晋升到老年代,在这个推断的前提下,Eden区过大,并且在youngGC时,eden中存活下来的对象超过survior区的大小,会导致对象未达到晋升年龄就进去老年代。

      调整启动参数后观察,发现老年代内存稳定,不再持续变大。

posted on 2021-12-01 18:51  阿姆斯特朗回旋炮  阅读(569)  评论(0编辑  收藏  举报

导航