一次有趣的线上频繁full gc问题排查记录2.0(诡异的fullgc)

接着上次 我分享的博文,

一次有趣的线上频繁full gc问题排查记录 V1.0一次有趣的线上频繁full gc问题排查记录 V1.0

我继续挖了一下本次线上遇到fullgc的根本原因 发现事情并没有那么简单

我发现一点 当jvm的老年代压根就没满的情况下 触发的fullgc,老年代600M就开始疯狂gc,由于这点我们可排除老年代满的这点

通过jgcutil 我们也可以看到持久代也没有溢出 因此也不可能是 持久代满的情况

这边我们做一个小总结

1,新生代:(1)所有对象创建在新生代的Eden区,当Eden区满后触发新生代的Minor GC,将Eden区和非空闲Survivor区存活的对象复制到另外一个空闲的Survivor区中。(2)保证一个Survivor区是空的,新生代Minor GC就是在两个Survivor区之间相互复制存活对象,直到Survivor区满为止。

2,老年代:当Survivor区也满了之后就通过Minor GC将对象复制到老年代。老年代也满了的话,就将触发Full GC,针对整个堆(包括新生代、老年代、持久代)进行垃圾回收。

3,持久代:持久代如果满了,将触发Full GC。

JVM垃圾回收中full GC的触发条件可能有哪些呢?

(1)老年代满

(2)持久代满

(3)System.gc()

因此我们还是回到代码去排查问题(写的代码。或者调用的框架底层调用了system.gc),通过逐步删除代码,找到了触发fgc的根本原因在这行代码

一步步的追溯源码

我们可以发现的确底层调用了system.gc的方法

于是我们把无关的业务代码删除只让他去循环的调用该方法

结果证明了我们的猜想

但是验证到这还不够因此我在本地写了一个main方法来,并且开启了jvm参数打印,以及一步步debug代码到源码级别 来观察fgc的情况

执行main方法,出现了fullgc的情况,并且情况和生产类似

执行debug,的确触发了fullgc

检查发现POI源码中存在Sytem.gc 真是防不胜防啊,怎么办?

通过阅读源码 我们发现了一个禁用gc的参数

getGCDisabled

因此我们再改造一下 我们的测试类

再次运行,发现没有full gc的情况了

总结:

可能这一个框架有可以禁用gc,一个大项目用了很多框架我不可能每个都看看源码吧,所以需要提前做性能的测试,发现里面的System.gc();解决他。

但是有可能有的框架本身必须需要进行gc,例如大数据这块。其实这就是调优去衡量,那些需要gc,那些不需要gc

太极玩的就是一个平衡,并不是这个事情多严重,但是这个坑一定得注意,这就是性能测试的必要性。小功能的jar自带的gc,可能导致这个系统的gc,本来10秒一次的gc,因为这个小功能1秒中gc一次,导致整个系统也是1秒1个次,本身开发系统就是为了减少耦合

并且通过上边的代码应该可以明白,jvm在做回收统计的时候真得会一个一个统计的。开发时,借鉴线程安全,接触到大数据的地方,就有泄露的可能,被反被执行,也有可能出现泄露

更多内容,可以关注我的公众号【江方方】

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值