为什么新生代有两个Survivor分区

2023-11-10 19:31

本文主要是介绍为什么新生代有两个Survivor分区,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

分代收集器会把内存空间分为:老年代和新生代两个区域,而新生代又会分为:Eden区和两个Survivor区(From Survivor、To Survivor)。
在这里插入图片描述
可以看出,Eden区和Survivor分区的默认比例是8:1:1。这个值可以通过:-XX:SurvivorRatio设定,默认值,:-XX:SurvivorRatio=8。

新生代和老年代的默认情况下内存占比是1:2,该值可以通过:-XX:NewRatio来设定。

1.为什么要有Survivor区

如果没有Survivor,Eden区每进行异常Minor GC,存活的对象就会被送到老年代。老年代很快被填满,触发Major GC(因为Major GC一般伴随着Minor GC,也可以看做是触发了Full GC。老年代的内存空间大于新生代,进行一次Full GC消耗的时间比Minor GC长的多。
Full GC会影响大型程序的执行和响应速度,更不要说某些连接会因为超时发生连接错误了。

如果没有Survivor的情况下,如何避免Full GC的频繁发生呢。

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

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

为什么要设置两个Survivor区呢

设置两个Survivor区的最大好处就是解决了碎片化。
如果只有一个Surivor区:

刚刚新建的对象存放在Eden区,一旦Eden区满了,就会触发一次Minor GC,Eden中的存活对象就会被移动到Survivor区。这样继续循环下去,下一次Eden满了的时候,问题来了,此时进行Minor GC,Eden和Survivor各有一些存活对象,如果此时把Eden区的存活对象硬放到Survivor区,很明显这两部分对象所占有的内存是不连续的,也就导致了内存碎片化。
在这里插入图片描述
碎片化带来的风险是极大的,严重影响Java程序的性能。堆空间被散布的对象占据不连续的内存,最直接的结果,就是堆中没有足够大的连续内存空间,接下去如果程序需要给一个内存需求很大的对象分配内存,那么就会需要整理空间。

因此,需要建立两块Survivor区,刚刚新建的对象存放在Eden区,经历过一次Minor GC后,Eden中的存活对象就会被移动到第一块的survivor space S0,Eden被清空;等Eden区再满了,就再触发一次Minor GC,Eden和S0中存活的对象就会被复制送入到第二块的survivor space S1,避免了碎片化的发生。
S0和Eden被清空后,然后进行下一轮S0和S1交换角色,原S0变成S1,原S1变成S0。如此循环往复,当survivor区中有对象的复制次数达到16次,也就是16次 Minor GC都没有回收该对象,该对象就会被送到老年代。

上述机制的最大好处就是,整个过程中,永远有一个survivor是空的,另一个非空的survivor space没有碎片。

那么为什么survivor为什么不分更多块呢

如果Survivor区再细分的话,每一块的空间就会很小,很容易导致Survivor区满,而且两块的Survivor区,已经足够支持标记-复制算法的进行。应该是经过权衡之后的结果。
https://blog.csdn.net/antony9118/article/details/51425581

这篇关于为什么新生代有两个Survivor分区的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/384795

相关文章

MySQL 定时新增分区的实现示例

《MySQL定时新增分区的实现示例》本文主要介绍了通过存储过程和定时任务实现MySQL分区的自动创建,解决大数据量下手动维护的繁琐问题,具有一定的参考价值,感兴趣的可以了解一下... mysql创建好分区之后,有时候会需要自动创建分区。比如,一些表数据量非常大,有些数据是热点数据,按照日期分区MululbU

C# 比较两个list 之间元素差异的常用方法

《C#比较两个list之间元素差异的常用方法》:本文主要介绍C#比较两个list之间元素差异,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录1. 使用Except方法2. 使用Except的逆操作3. 使用LINQ的Join,GroupJoin

java中新生代和老生代的关系说明

《java中新生代和老生代的关系说明》:本文主要介绍java中新生代和老生代的关系说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、内存区域划分新生代老年代二、对象生命周期与晋升流程三、新生代与老年代的协作机制1. 跨代引用处理2. 动态年龄判定3. 空间分

MySQL数据库实现批量表分区完整示例

《MySQL数据库实现批量表分区完整示例》通俗地讲表分区是将一大表,根据条件分割成若干个小表,:本文主要介绍MySQL数据库实现批量表分区的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考... 目录一、表分区条件二、常规表和分区表的区别三、表分区的创建四、将既有表转换分区表脚本五、批量转换表为分区

MySQL 分区与分库分表策略应用小结

《MySQL分区与分库分表策略应用小结》在大数据量、复杂查询和高并发的应用场景下,单一数据库往往难以满足性能和扩展性的要求,本文将详细介绍这两种策略的基本概念、实现方法及优缺点,并通过实际案例展示如... 目录mysql 分区与分库分表策略1. 数据库水平拆分的背景2. MySQL 分区策略2.1 分区概念

Mysql表如何按照日期字段的年月分区

《Mysql表如何按照日期字段的年月分区》:本文主要介绍Mysql表如何按照日期字段的年月分区的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、创键表时直接设置分区二、已有表分区1、分区的前置条件2、分区操作三、验证四、注意总结一、创键表时直接设置分区

MySQL大表数据的分区与分库分表的实现

《MySQL大表数据的分区与分库分表的实现》数据库的分区和分库分表是两种常用的技术方案,本文主要介绍了MySQL大表数据的分区与分库分表的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有... 目录1. mysql大表数据的分区1.1 什么是分区?1.2 分区的类型1.3 分区的优点1.4 分

C语言实现两个变量值交换的三种方式

《C语言实现两个变量值交换的三种方式》两个变量值的交换是编程中最常见的问题之一,以下将介绍三种变量的交换方式,其中第一种方式是最常用也是最实用的,后两种方式一般只在特殊限制下使用,需要的朋友可以参考下... 目录1.使用临时变量(推荐)2.相加和相减的方式(值较大时可能丢失数据)3.按位异或运算1.使用临时

java两个List的交集,并集方式

《java两个List的交集,并集方式》文章主要介绍了Java中两个List的交集和并集的处理方法,推荐使用Apache的CollectionUtils工具类,因为它简单且不会改变原有集合,同时,文章... 目录Java两个List的交集,并集方法一方法二方法三总结java两个List的交集,并集方法一

Python如何计算两个不同类型列表的相似度

《Python如何计算两个不同类型列表的相似度》在编程中,经常需要比较两个列表的相似度,尤其是当这两个列表包含不同类型的元素时,下面小编就来讲讲如何使用Python计算两个不同类型列表的相似度吧... 目录摘要引言数字类型相似度欧几里得距离曼哈顿距离字符串类型相似度Levenshtein距离Jaccard相