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

转载自:http://blog.csdn.net/antony9118/article/details/51425581

1.为什么要有Survivor区

  首先思考设置Survivor区的意义在哪里?
  如果没有Survivor,Eden区每进行一次Minor GC,存活的对象就会被送到老年代。老年代很快被填满,触发Major GC(也可以看做触发了Full GC)。老年代的内存空间远大于新生代,进行一次Full GC消耗的时间比Minor GC长得多。频发的Full GC消耗的时间是非常多的,这一点会影响大型程序的执行和响应速度。

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

  1. 增加老年代空间
    使更多的存活对象才能填满老年代,降低Full GC频率,但随着老年代空间加大,一旦发生Full GC,执行所需要的时间更长。
  2. 减少老年代空间
    使Full GC所需时间减少,但老年代会很快被存活对象填满,Full GC频率增加。

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

  可以得到第一条结论:Survivor的存在意义,就是减少被送到老年代的对象,进而减少Full GC的发生,Survivor的预筛选保证,只有经历几次Minor GC还能在新生代中存活的对象,才会被送到老年代。

2.为什么要设置两个Survivor区

  设置两个Survivor区最大的好处就是解决了碎片化。
  下面来分析一下,为什么一个Survivor区不行?假设现在只有一个survivor区,一旦Eden满了,触发一次Minor GC,Eden中的存活对象就会被移动到Survivor区,这样继续循环下去。问题来了,进行Minor GC时,Eden和Survivor各有一些存活对象,把Eden区的存活对象放到Survivor区,Survivor区的过期对象移除,很明显操作之后Survivor区对象所占有的内存是不连续的,也就导致了内存碎片化。
  碎片化带来的风险是极大的,严重影响JAVA程序的性能。堆空间被散布的对象占据不连续的内存,最直接的结果就是,堆中没有足够大的连续内存空间,就会触发Major GC。
  那么,如果建立两块Survivor区,刚刚新建的对象在Eden中,经历一次Minor GC,Eden中的存活对象就会被移动到第一块survivor space S0,Eden被清空;等Eden区再满了,就再触发一次Minor GC,Eden和S0中的存活对象又会被复制送入第二块survivor space S1(这种复制算法保证了S1中来自S0和Eden两部分的存活对象占用连续的内存空间,避免了碎片化的发生)。S0和Eden被清空,然后下一轮S0与S1交换角色,如此循环往复。如果对象的复制次数达到阈值,该对象就会被送到老年代中。
  上述机制最大的好处就是,整个过程中,永远有一个survivor space是空的,另一个非空的survivor space无碎片。

在Java虚拟机(JVM)中,新生代(Young Generation)是用来存放新创建对象的域,它包括一个Eden两个Survivor(通常称为S0和S1)。理解这些域的工作原理对于优化应用程序性能和准备面试都是十分重要的。 参考资源链接:[Java面试必备:JVM内存与垃圾回收深度解析](https://wenku.csdn.net/doc/b18dt45q4f?spm=1055.2569.3001.10343) 首先,Eden是大多数新对象首先被创建的地方,当Eden不足以存放新对象时,就会触发一次称为Minor GC(次要垃圾回收)的事件。Minor GC的主要任务是清除不再被引用的对象,以腾出空间给新对象。在进行Minor GC时,存活的对象首先会被移动到一个Survivor(通常是S0),而另一Survivor(S1)则保持空闲。随着应用程序的运行,Eden的对象会不断被复制到Survivor,直至Survivor无法容纳时,仍然存活的对象会被提升(promote)到老年代(Old Generation)。 Survivor的作用是为了保存Minor GC后存活的对象,并为这些对象提供足够的存活空间。这样可以保证老年代空间不会因为频繁的垃圾回收而过早地被使用。在Minor GC过程中,一般情况下,一个Survivor作为to域,另一个作为from域。当Eden进行垃圾回收时,存活的对象会被复制到to域的Survivor中。随着垃圾回收的进行,两个Survivor会进行角色交换,之前to域的Survivor在下一次Minor GC时将作为from域。 这种新生代的设计对于垃圾回收策略的影响体现在两个方面: 1. **分代假说**:根据观察,大多数对象很快就不再被引用,而存活下来的对象会存活更久。因此,新生代的EdenSurvivor的设计符合这种假说,使得垃圾回收器能高效地回收大部分对象,只有少数对象会被移动到老年代。 2. **分代收集**:由于对象的这种分配和生存特性,JVM采用了分代收集算法。这种算法通过不同的垃圾回收策略,针对新生代使用如复制算法来快速处理新创建的对象,而对老年代则使用标记-清除或标记-整理算法来处理长时间存活的对象。 了解EdenSurvivor如何协同工作,以及它们如何影响垃圾回收策略,能够帮助开发者更加有效地监控和调整JVM的内存管理,从而提升应用程序的性能。在准备面试时,这些知识也会帮助面试者展示对JVM的深刻理解。 如果你希望更深入地了解JVM内存管理及垃圾回收的各个方面,请务必查阅这份资料:《Java面试必备:JVM内存与垃圾回收深度解析》。这份资源不仅涵盖了新生代和老年代的设计原理,还详细解析了各种垃圾回收器的工作机制,以及如何针对不同代选择合适的垃圾回收算法,是Java开发者在面试前不可或缺的复习资料。 参考资源链接:[Java面试必备:JVM内存与垃圾回收深度解析](https://wenku.csdn.net/doc/b18dt45q4f?spm=1055.2569.3001.10343)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值