内存空间|JVM年轻代标记复制过程深入分析
我们都知道Java对象存储在堆内存中 , 堆大小=年轻代+老年代 。默认情况下 , 年轻代与老年代的堆大小比例为1:2 , 即-XX:NewRatio=2 。年轻代结构
新创建的对象总是会放入年轻代中 , 年轻代分为Eden和两个Survivor区 , Survivor区被命名为From和To以示区分 , 可以使用-Xmn2g来设置年轻代大小为2G 。
默认情况下 , Edem:From:To=8:1:1 , 即-XX:SurvivorRatio=8 , Eden与一个Survivor区的比值 。JVM每次只会使用Eden区和其中的一块Survivor区为对象服务 , 所以无论什么时候 , 总有一块Survivor区是空闲着的 , 年轻代实际可用的内存空间为9/10的年轻代空间 。标记复制过程
年轻代采用标记复制算法进行垃圾回收 , 因为绝大部分对象都是朝生夕灭的 , 真正需要复制的对象非常少 。复制算法就是把对象从一个区域复制到另外一个空白区域 , 因此不像老年代的标记清除算法 , 不存在内存碎片的问题 。
(1)新创建的对象总是放入Eden区 , 当Eden区满后会触发MinorGC(YoungGC) 。当执行MinorGC时 , 把Eden和From区中存活的对象复制到To区 , 然后清空Eden和From区 , 并把这些对象的年龄设置为1 。
【内存空间|JVM年轻代标记复制过程深入分析】(2)新创建的对象仍然进入Eden区 , 当Eden区满后会触发MinorGC(YoungGC) 。这时把Eden和To区中存活的对象复制到From区 , 然后清空Eden和To区 , 并把这些对象的年龄设置为2 , 依次循环下去 。
之后对象在 Survivor 区每熬过一次MinorGC , 对象的年龄+1 , 当对象的年龄达到15时(最大值15 , 对象头里面4位表示年龄 。可以通过参数-XX:MaxTenuringThreshold设定) , 这些对象就会晋升到老年代 。但是对于一些较大的对象 , 即需要分配一块较大的连续内存空间的则是直接晋升到老年代(可以通过参数-XX:PretenureSizeThreshold设定) , 大于这个设置值的对象直接晋升到老年代 , 目的是避免在Eden区及两个Survivor区之间发生大量的对象复制 。
文章图片
文章图片
为什么有两个Survivor区
(1)如果没有Survivor区 , 每执行一次MinorGC , 活着的对象全部进入老年代 , 老年代很快被填满;
(2)如果只有一个Survivor区 , 缺点:MinorGC频率增加;浪费50%的内存空间 。
MinorGC频率增加:当执行第一次MinorGC时 , Eden区中活着的对象复制到Survivor区 , 然后清空Eden区 , 那么在执行第二次MinorGC前 , 对象都被分配到Survivor区 , 由于Survivor区比较小 , 很快就会触发第二次MinorGC 。即使Eden和Survivor对半分 , 也是50%触发Minor GC , 而有两个Survivor达到80%才触发MinorGC , MinorGC的频率大大降低 。
浪费50%的内存空间:标记复制算法必须保证有一块空闲的内存空间供对象复制 , 如果只有一个Survivor区 , 假如Eden占80%、Survivor占20% , 第一次MinorGC内存空间只浪费了20% , 但第二次的时候 , 会浪费80% , 无论如何都会浪费50%的内存空间 , 而两个Survivor区只浪费10%的内存空间 , 因为只有一个Survivor区是空的 。
推荐阅读
- 放飞自我|无人的如月车站 不存在的平行空间
- 掌上社会|四维空间的物种就是鬼,鬼魂以电磁波的方式存在[科学家实验发现]
- 李二蛋进城|中国未来的5大超级工程:1、中欧高铁 150亿元2、中国空间站
- 中年|中国光伏还有多少空间?
- ZAKER|未来五年带动数十亿投资空间,全球疫情拐点曙光将至
- 空调|化零为整,为生活释放更多空间,EBC英宝纯空气环境机敬请期待
- 综艺|韩国演员金载沅出演综艺,出道 20 年,首次公开私人空间和8岁儿子
- 磊磊趣闻|美国宇航局在国际空间站附近再次拍摄到UFO接近?
- 5G手机,荣耀手机|最值得入手的三款5G手机,8+128G大内存,仅1600元!
- 5G手机|最值得入手的三款5G手机,8+128G大内存,仅1600元!
