为什么新生代内存需要有两个Survivor区?

常见的GC算法,我们应该知道,例如:

  •  标记—清除算法:回收之后存在大量的【内存碎片】,存在【效率】和【空间】问题!为了解决效率问题,引出了复制算法!
  •  复制算法
  •  标记—整理算法
  •  分代收集算法

那么问题来了,在JVM的新生代内存中,为什么除了Eden区,还要设置两个Survivor区?

 一、为什么要有Survivor区

       先不去想为什么有两个Survivor区,第一个问题是,设置Survivor区的意义在哪里?

       

      如果没有Survivor,Eden区每进行一次Minor GC,存活的对象就会被送到老年代。

      老年代很快被填满,触发Major GC(因为Major GC一般伴随着Minor GC,也可以看做触发了Full GC)。

      老年代的内存空间远大于新生代,进行一次Full GC消耗的时间比Minor GC长得多。

      你也许会问,执行时间长有什么坏处?频发的Full GC消耗的时间是非常可观的,这一点会影响大型程序的执行和响应速度,更不要说某些连接会因为超       时发生连接错误了。

      好,那我们来想想在没有Survivor的情况下,有没有什么解决办法,可以避免上述情况:

       

     显而易见,没有Survivor的话,上述两种解决方案都不能从根本上解决问题。

     我们可以得到第一条结论:

        Survivor的存在意义,就是减少被送到老年代的对象,进而减少Full GC的发生

        Survivor的预筛选保证,只有经历16次Minor GC还能在新生代中存活的对象,才会被送到老年代。

二、为什么要设置两个Survivor区

           设置两个Survivor区最大的好处就是解决了碎片化,下面我们来分析一下:

           为什么一个Survivor区不行?第一部分中,我们知道了必须设置Survivor区。假设现在只有一个survivor区,我们来模拟一下流程: 

           刚刚新建的对象在Eden中,一旦Eden满了,触发一次Minor GC,Eden中的存活对象就会被移到Survivor区。

          这样继续循环下去,下一次Eden满了的时候,问题来了,此时进行Minor GC,Eden和Survivor各有一些存活对象,如果此时把Eden区的存活对象硬             放到Survivor区,很明显这两部分对象所占有的内存是不连续的,也就导致了内存碎片化。 

          其中色块代表对象,白色框分别代表Eden区(大)和Survivor区(小)。Eden区理所当然大一些,否则新建对象很快就导致Eden区满,进而触发                 Minor GC,有悖于初衷。

          

          碎片化带来的风险是极大的,严重影响Java程序的性能。

          堆空间被散布的对象占据不连续的内存,最直接的结果就是,堆中没有足够大的连续内存空间,接下去如果程序需要给一个内存需求很大的对象分配           内存。就不得不提前进行一次垃圾回收。

           那么,顺理成章的,应该建立两块Survivor区,刚刚新建的对象在Eden中,经历一次Minor GC,Eden中的存活对象就会被移动到第一块survivor space S0,Eden被清空;等Eden区再满了,就再触发一次Minor GC,Eden和S0中的存活对象又会被复制送入第二块survivor space S1(这个过程非常重要,因为这种复制算法保证了S1中来自S0和Eden两部分的存活对象占用连续的内存空间,避免了碎片化的发生)。S0和Eden被清空,然后下一轮S0与S1交换角色,如此循环往复。如果对象的复制次数达到16次,该对象就会被送到老年代中。下图中每部分的意义和上一张图一样,就不加注释了。 

           

             复制算法最大的好处就是:整个过程中,永远只有一个Survivor空间是空的,另一个非空的Survivor空间无碎片。

              那么,Survivor为什么不分更多块呢?比方说分成三个、四个、五个?显然,如果Survivor区再细分下去,每一块的空间就               会比较小,很容易导致Survivor区满,因此,我认为两块Survivor区是经过权衡之后的最佳方案。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值