Java堆中的年轻代为什么要设置Survivor区?为什么还要设置两个Survivor区?

1 年轻代只设置一个Eden区行不行?

如果只设置一个Eden区,那么没进行一次MinorGC,存活的对象就会被送入老年代,老年代很快被填满,就会触发MajorGC,因为MajorGC之前会先进行一次MinorGC,所以也可以看做是发生了Full GC,Full GC消耗的时间要远远大于Minor GC,这样会增加系统停顿时间。那么,你们也许会想,可以增加老年代的空间,减少Full GC的频率,可以是频率虽然降低了,但是由于老年代存储的对象太多,一旦发生Full GC,单次GC的时间增加了,系统停顿时间依然很长。反之,单次GC时间减少,但是GC频率增加了,结果还是一样的。
所以,我们减少Full GC的方案只有一个:减少往老年代发送的对象,进而更慢地触发Full GC。所以,我们才需要Survivor区来进行筛选,只要经历了16次Minor GC还能在年轻代存活的对象才有资格送往老年代。

2 设置一个Eden区和一个Survivor区行不行?

我们已经知道了必须需要设置Survivor区,如果只要一个Survivor区,MinorGC流程是:

  • 把new对象放在Eden中,一旦Eden满了,触发一次Minor GC,Eden中的存活对象就会移动到Survivor区,同时Eden区被清空。
  • 然后继续new对象放在Eden区中,一旦Eden满了,又触发一个Minor GC,此时,Eden和Survivor中各有一些存活的对象,尤其是Survivor区发生了GC后,剩余存活的对象肯定不是紧密排列的,如果此时把Eden区中存活对象强行移动到Survivor区中,由于这Survivor区域的对象不是连续的,所以会产生内存碎片。

所以,我们建立两个Survivor区看看如何。

3 建立两个Survivor区怎么样?

建立两个Survivor区,分别是S0和S1,MinorGC流程如下:

  • 把new的对象放在Eden区中,一旦Eden满了,触发一次Minor GC,Eden区中存活的对象会送到S0中,Eden被清空;
  • 再次new对象放入Eden区中,Eden又满了,触发Minor GC,Eden和S0中存活的对象放入到S1中,然后S0和Eden清空,然后S0和S1交换角色,S1变成了S0,作为下一次GC的主要目标,S0变成了S1,存放下一次GC存活的对象。
  • 如此循环往复,对象头的分代年龄达到16次,则会被送到老年代中。

有两个Survivor的好处就是:永远有一个S区是空的,另外一个S区无碎片。如果Survivor细分为更多块,每一块的空间会比较小,很容易导致Survivor满,对象的分代年龄增加的越快,导致送往老年代的对象越多,所以两个S区是经过权衡后的最佳方案。

  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值