新生代内存中为什么要有两个survivor区
首先是关于新生代中的内存分布的描述:
新生代中的对象都是“朝生夕死”的对象,所以每次gc存活的对象很少,于是在新生代中采用的垃圾回收算法是“复制算法”。
将新生代的内存分为一块较大的Eden区域和两块较小的Survivor区域。每次使用Eden和其中一块Survivor空间。回收的时候,将Eden和Survivor中还存活着的对象一次性地复制到另一块空间上,最后清理Eden和刚才用过的Survivor空间。
HotPost虚拟机默认Eden和Survivor的大小比例是8:1,也就是每次新生代中可用内存空间为整个新生代容量的90%(80%+10%),只有百分之10%的内存会被浪费。
当Survivor空间不够放的时候,需要依赖其他内存(这里指老年代)进行分配担保。
这是书上(《深入理解Java虚拟机》)对于复制算法的描述。
但在后面更详细地讲内存分配与回收策略的时候:
书上说:在大多数情况下,对象在新生代Eden区中分配。当Eden区没有足够空间进行分配时,虚拟机发起一次Minor GC。
这就有点疑惑了,照这么说超过Eden就执行mimor gc,然后survivor只是用来放存活的对象的,那为什么要两个呢?
这是为了解决内存碎片化的问题。
假设我们现在只有一个Survivor空间。
刚刚新建的对象在Eden中,一旦Eden满了,触发一次Minor GC,Eden中的存活对象就会被移动到Survivor区。下一次Eden满了的时候,问题来了,此时进行Minor GC,Eden和Survivor各有一些存活对象,因为只有一个Survivor,所以Eden第二次的gc发现的存活对象也是放在唯一的一个Survivor区域中。但此时把Eden区的存活对象硬放到Survivor区,很明显这两部分对象所占有的内存是不连续的,也就导致了内存碎片化。
看图来理解:
(图片来自:https://blog.csdn.net/antony9118/article/details/51425581)

第一个图,是Eden中蓝色的内存装满了,要gc,然后Survivor区中的黄色内存,是上一次gc从Eden过来的存活对象。
第二个图是触发gc后,通过可达性判断,把活着的对象找出来。蓝色的Eden中剩一小丢存活对象,注意Survivor区中的对象也会死掉!所以现在Survivor区的对象也不是从头充满Survivor区域的了。
然后第三个图便是把Eden存活的对象放到Survivor中去,这时就产生了碎片化。
那么要怎么解决这个问题呢?
- 试图将Eden区存活的对象转移到survivor中,努力适应这种不连续的空间。但是不连续的空间会导致再分配大对象的时候,由于没有连续的空间来分配,会导致提前垃圾回收。
- 将survivor中的所有存活对象向下移动来消除碎片,然后将所有的存活对象移入其中。这样做会降低效率。
- 把两个区域中的所有存活对象都转移到完全独立的空间中,也就是第二块Survivor中,这样就可以留出一块完全空着的Eden和Survivor了,下次GC的时候再重复这个流程
显然方案三好点hh,所以我们便要有两个Survivor区。
那么,顺理成章的,应该建立两块Survivor区。
刚刚新建的对象在Eden中,经历一次Minor GC,Eden中的存活对象就会被移动到第一块survivor space S0,Eden被清空;等Eden区再满了,就再触发一次Minor GC,Eden和S0中的存活对象又会被复制送入第二块survivor space S1(这个过程非常重要,因为这种复制算法保证了S1中来自S0和Eden两部分的存活对象占用连续的内存空间,避免了碎片化的发生)。S0和Eden被清空,然后下一轮S0与S1交换角色,如此循环往复。
看图:
(图片来自:https://blog.csdn.net/antony9118/article/details/51425581)

上述机制最大的好处就是,整个过程中,永远有一个survivor space是空的,另一个非空的survivor space无碎片。
参考文章:
https://blog.csdn.net/antony9118/article/details/51425581
https://www.jianshu.com/p/a5fd5bf93d26
新生代内存中为什么要有两个survivor区的更多相关文章
- 在JVM的新生代内存中,为什么除了Eden区,还要设置两个Survivor区
在JVM的新生代内存中,为什么除了Eden区,还要设置两个Survivor区? 1 为什么要有Survivor区 先不去想为什么有两个Survivor区,第一个问题是,设置Survivor区的意义在哪 ...
- JVM内存结构之二--新生代及新生代里的两个Survivor区(下一轮S0与S1交换角色,如此循环往复)、常见调优参数
一.为什么会有年轻代 我们先来屡屡,为什么需要把堆分代?不分代不能完成他所做的事情么?其实不分代完全可以,分代的唯一理由就是优化GC性能.你先想想,如果没有分代,那我们所有的对象都在一块,GC的时候我 ...
- 为什么新生代内存需要有两个Survivor区
转载自:http://blog.csdn.net/antony9118/article/details/51425581 在JVM的新生代内存中,为什么除了Eden区,还要设置两个Survivor区? ...
- JVM内存结构--新生代及新生代里的两个Survivor区(下一轮S0与S1交换角色,如此循环往复)、常见调优参数
一.为什么会有年轻代 我们先来屡屡,为什么需要把堆分代?不分代不能完成他所做的事情么?其实不分代完全可以,分代的唯一理由就是优化GC性能.你先想想,如果没有分代,那我们所有的对象都在一块,GC的时候我 ...
- 为什么新生代内存需要有两个Survivor区?
对于常见的GC算法,我们都应该知道,例如:标记清除算法.复制算法.标记整理算法等.标记清除算法由于回收之后存在大量的内存碎片,存在效率和空间问题!为了解决效率问题,引出了复制算法!熟悉GC算法的小伙伴 ...
- JVM体系结构之六:堆Heap之2:新生代及新生代里的两个Survivor区(下一轮S0与S1交换角色,如此循环往复)、常见调优参数
一.为什么会有年轻代 我们先来屡屡,为什么需要把堆分代?不分代不能完成他所做的事情么?其实不分代完全可以,分代的唯一理由就是优化GC性能.你先想想,如果没有分代,那我们所有的对象都在一块,GC的时候我 ...
- 新生代Eden与两个Survivor区的解释
文章出处:http://ifeve.com/jvm-yong-generation/ 聊聊JVM的年轻代 1.为什么会有年轻代 我们先来屡屡,为什么需要把堆分代?不分代不能完成他所做的事情么?其实不分 ...
- 内存中 OLTP - 常见的工作负荷模式和迁移注意事项(一)
----------------------------我是分割线------------------------------- 本文翻译自微软白皮书<In-Memory OLTP – Comm ...
- 游标-----内存中的一块区域,存放的是select 的结果
游标-----内存中的一块区域,存放的是select 的结果 游标用来处理从数据库中检索的多行记录(使用SELECT语句).利用游标,程序可以逐个地处理和遍历一次检索返回的整个记录集 ...
随机推荐
- java多线程-多线程常识
线程和进程的区别是什么?进程是一个正在运行的软件程序,打开资源管理器可以看到好多正在运行的进程,而线程则是程序中的顺序控制流,只能使用分配给程序的资源和环境.一个进程至少存在一个线程(主线程). 在j ...
- codeforces 465C.No to Palindromes! 解题报告
题目链接:http://codeforces.com/problemset/problem/464/A 题目意思:给出一个长度为 n 且是 tolerable 的字符串s,需要求出字典序最小的长度也为 ...
- html5--3.16 button元素
html5--3.16 button元素 学习要点 掌握button元素的使用 button元素 用来建立一个按钮从功能上来说,与input元素建立的按钮相同 button元素是双标签,其内部可以配置 ...
- jsp报An error has occurred. See error log for more details. Argument not valid错误
An error has occurred. See error log for more details. Argument not valid 翻译过来是:一个错误已经发生.看到更多的细节错误日志 ...
- centos 安装配置kettle
安装JDK1.8: step1 下载JDK1.8 http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133 ...
- D3.JS V4 绘制中国地图
参考:http://bl.ocks.org/almccon/fe445f1d6b177fd0946800a48aa59c71 http://blog.csdn.net/lzhlzz/article/d ...
- c++之函数值传递和引用传递解析----关键在于理解函数return的实现机制(内存分配)
函数调用过程解析 func里的a存储在调用fun函数时开辟的栈空间里,这块栈只在调用func时对func可用,调用结束后返回的a,其实是暂存在寄存器里的(一般情况下是eax),而返回到main里时,m ...
- PB调用C# Windows窗体
以下是PB中的代码:String ls_filenameLong ll_wstyle=1long ll_hwnd,ll_nShowCmdstring ls_lpOperation,ls_lpFile, ...
- PHP错题误区
1,$bool = TRUE;echo gettype($bool); //这个输出类型:booleanecho is_string($bool); //这个用echo是不能输出布尔型的,只有va ...
- 【216】◀▶ IDL 字符串操作说明 (黑底)
参考:String Processing Routines —— 字符串处理函数 参考:IDL_String Methods 01 STRING 返回字符串. 02 STRCMP 比较字符串, ...