为什么新生代有两个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

相关文章

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

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

两个月冲刺软考——访问位与修改位的题型(淘汰哪一页);内聚的类型;关于码制的知识点;地址映射的相关内容

1.访问位与修改位的题型(淘汰哪一页) 访问位:为1时表示在内存期间被访问过,为0时表示未被访问;修改位:为1时表示该页面自从被装入内存后被修改过,为0时表示未修改过。 置换页面时,最先置换访问位和修改位为00的,其次是01(没被访问但被修改过)的,之后是10(被访问了但没被修改过),最后是11。 2.内聚的类型 功能内聚:完成一个单一功能,各个部分协同工作,缺一不可。 顺序内聚:

2024年AMC10美国数学竞赛倒计时两个月:吃透1250道真题和知识点(持续)

根据通知,2024年AMC10美国数学竞赛的报名还有两周,正式比赛还有两个月就要开始了。计划参赛的孩子们要记好时间,认真备考,最后冲刺再提高成绩。 那么如何备考2024年AMC10美国数学竞赛呢?做真题,吃透真题和背后的知识点是备考AMC8、AMC10有效的方法之一。通过做真题,可以帮助孩子找到真实竞赛的感觉,而且更加贴近比赛的内容,可以通过真题查漏补缺,更有针对性的补齐知识的短板。

两个长数字相加

1.编程题目 题目:要实现两个百位长的数字直接相加 分析:因为数字太长所以无法直接相加,所以采用按位相加,然后组装的方式。(注意进位) 2.编程实现 package com.sino.daily.code_2019_6_29;import org.apache.commons.lang3.StringUtils;/*** create by 2019-06-29 19:03** @autho

创建一个大的DIV,里面的包含两个DIV是可以自由移动

创建一个大的DIV,里面的包含两个DIV是可以自由移动 <body>         <div style="position: relative; background:#DDF8CF;line-height: 50px"> <div style="text-align: center; width: 100%;padding-top: 0px;"><h3>定&nbsp;位&nbsp;

在二叉树中找到两个节点的最近公共祖先(基于Java)

如题  题解 public int lowestCommonAncestor(TreeNode root, int o1, int o2) {//记录遍历到的每个节点的父节点。Map<Integer, Integer> parent = new HashMap<>();Queue<TreeNode> queue = new LinkedList<>();parent.put(roo

Java中计算两个日期间隔多少天

String dbtime1 = "2017-02-23";  //第二个日期 String dbtime2 = "2017-02-22";  //第一个日期 //算两个日期间隔多少天 SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); Date date1 = format.parse(dbtime1); Date dat

Java利用正则表达式获取指定两个字符串之间的内容

package com.starit.analyse.util;import java.text.SimpleDateFormat;import java.util.ArrayList;import java.util.List;import java.util.regex.Matcher;import java.util.regex.Pattern;public class DealSt

git如何灵活切换本地账号对应远程github的两个账号

git如何灵活切换本地账号对应远程github的两个账号 问题: 有时候我们会同时维护两个github的账号里面的仓库内容,这时候本地git需要频繁的切换ssh,以方便灵活的与两个账号的仓库可以通信。这篇日记将阐述我是怎么解决这个问题的。1. 第一个账户 生成本地SSH2. 注意 我们要设置第二个账户的 本地 SSH 时3. 两个账号来回切换 问题: 有时候我们会同时维护两个git

交换两个变量数值的3种方法

前言:交换两个数值可不是"a = b,b = a"。这样做的话,a先等于了b的值;当“b = a”后,因为此时a已经等于b的值了,这个语句就相当于执行了b = b。最终的数值关系就成了a == b,b == b。 下面教给大家3种交换变量数值的方法: 目录 1. 中介法 2. 消和法 3. 异或法 4. 总结 1. 中介法 中介法(又称 临时变量法 或 酱油法),其中心