java gc_Java GC分析记录

Java GC记录

近来、项目没有特别忙碌的时候,抽空看了下生产环境的项目运行状况,我们的项目一直运行速度不是很快,偶尔会出现卡顿的现象,这点给人的体验感觉也就不那么好了。先抛个测试环境截图(生产环境不方便,单参数设置类似):

cc6b7c05bbd9d73e1c7e830a220910a9.png

由上图可以看出,系统分配的堆内存4G,非堆内存最大2G,理论上、这个数值对于一般的项目绝对是够用的了;然鹅、并非如此,事实情况确是:

b9abd31a3cd3e3734eb22351b644397f.png

对于系统GC的记录统计为:

723676-20180228144305245-519522160.png

到这里、似乎还是看不出为何会产生这么多次的Full GC(大神应该已经察觉出上面的问题),再来看一张图:

5361120a5970976ba69d0e306d767703.png

似乎问题在这里已经浮现了,虽然我们给Java的堆内存、非堆内存都分配了不少空间,但真正使用的到的空间,以及它们之间如何分配,却没有限定。如上图存在的问题:

整个堆内存年轻代与老年代分别各占1.25G和2.67G,比例大约1:2.

永生带使用内存峰值也就只有380M

整个堆内存与非堆内存总共分配4.52G,实际使用峰值时也只有3.87G

现在、再分析下造成频繁Full GC的原因,了解过JVM GC知识的基本都清楚当在年轻代new一个对象时,如果年轻代没有足够的内存会进行一次Minor GC,当Minor GC之后仍无法提供足够的内存时,年轻代会将数据移向老年代,若老年代内存充足,则直接移向老年代,若老年代内存不足,就会进行一次Full GC,当Full GC结束后,老年代依旧无法提供足够的内存空间时,将抛出OutOfMemeryError错误;这里显然不是抛出了异常,而是频繁的进行Full GC。还有一种情况是非堆区内存不足时也会触发Full GC,然而,上面的数据显示非堆区内存充足,这里显然不是频繁Full GC的原因。所以、可以肯定这里的Full GC大多是老年代内存不足造成的。

看到上面的堆内存分布,我们知道老年代的内存占用峰值2.67G,依旧造成了频繁的Full GC,分析具体原因如下:

年轻代内存占比偏大,导致每次转移的Survivor区数据到老年代过大,致使老年代触发Full GC,即使老年代可能还没满。

系统new的大对象较多,在老年代对象存活时间久,致使剩余的内存空间不足

由于业务需求的原因,事实就是堆内存分配不足

看到上面的原因分析,解决办法如下:

修改年轻代与老年代堆内存使用比例(如1:3,1:4),使得Minor GC次数增多,从而减少Full GC次数。

优化业务代码,提高对象的复用,使得大对象的创建数目减少。

增加堆内存的分配

总之、具体问题具体分析,希望可以解决问题。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值