为什么新生代有两个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 分区与分库分表策略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相

使用Navicat工具比对两个数据库所有表结构的差异案例详解

《使用Navicat工具比对两个数据库所有表结构的差异案例详解》:本文主要介绍如何使用Navicat工具对比两个数据库test_old和test_new,并生成相应的DDLSQL语句,以便将te... 目录概要案例一、如图两个数据库test_old和test_new进行比较:二、开始比较总结概要公司存在多

C#比较两个List集合内容是否相同的几种方法

《C#比较两个List集合内容是否相同的几种方法》本文详细介绍了在C#中比较两个List集合内容是否相同的方法,包括非自定义类和自定义类的元素比较,对于非自定义类,可以使用SequenceEqual、... 目录 一、非自定义类的元素比较1. 使用 SequenceEqual 方法(顺序和内容都相等)2.

mysql数据库分区的使用

《mysql数据库分区的使用》MySQL分区技术通过将大表分割成多个较小片段,提高查询性能、管理效率和数据存储效率,本文就来介绍一下mysql数据库分区的使用,感兴趣的可以了解一下... 目录【一】分区的基本概念【1】物理存储与逻辑分割【2】查询性能提升【3】数据管理与维护【4】扩展性与并行处理【二】分区的

锐捷和腾达哪个好? 两个品牌路由器对比分析

《锐捷和腾达哪个好?两个品牌路由器对比分析》在选择路由器时,Tenda和锐捷都是备受关注的品牌,各自有独特的产品特点和市场定位,选择哪个品牌的路由器更合适,实际上取决于你的具体需求和使用场景,我们从... 在选购路由器时,锐捷和腾达都是市场上备受关注的品牌,但它们的定位和特点却有所不同。锐捷更偏向企业级和专