标记-复制算法将内存分为大小相同的两个区域,运行区域,预留区域,所有创建的新对象都分配到运行区域,当运行区域内存不够时,将运作区域中存活对象全部复制到预留区域,然后再清空整个运行区域内存,这时两块区域的角色也发生了变化,每次存活的对象就像皮球一下在运行区域与预留区域踢来踢出,而垃圾对象会随着整个区域内存的清空而释放掉,内存前后的状态参考下图:
文章插图
?标记-复制算法回收前后内存对比
标记-复制算法在大量垃圾对象的情况下,只需复制少量的存活对象,并且不会产生内存碎片问题,新内存的分配只需要移动堆顶指针顺序分配即可,很好的兼顾了效率与内存碎片的问题 。
标注-复制算法也存在缺点
预留一半的内存区域未免有些浪费了,并且如果内存中大量的是存活状态,只有少量的垃圾对象,收集器要执行更多次的复制操作才能释放少量的内存空间,得不偿失 。3.3 标记-整理算法标记-复制算法要浪费一半内存空间,且在大多数状态为存活状态时使用效率会很低,针对这一情况计算机科学家又提出了一种新的算法“标记-整理算法”,标记整理算法的标记阶段与其他算法一样,但是在整理阶段,算法将存活的对象向内存空间的一端移动,然后将存活对象边界以外的空间全部清空,如下图所示:
文章插图
?标记-整理算法回收前后内存对比
标记整理算法解决了内存碎片问题,也不存在空间的浪费问题,看上去挺美好的 。但是,当内存中存活对象多,并且都是一些微小对象,而垃圾对象少时,要移动大量的存活对象才能换取少量的内存空间 。四、新生代、老年代堆内存结构Java 堆内存空间新生代、老年代是如何划分的?对象创建后是如何分配到不同的区域的?结合下图可以知道,整个堆内存被分为了2个大的区域,新生代,老年代,默认情况下新生代占1/3的空间,老年代占2/3的空间,新生代又分为两个区 Eden区Survial区,Survial又分为S0、S1区 默认各占8/10与1/10,1/10的空间 。
不同的垃圾回收算法都有各自的优缺点,适应于不同的垃圾回收场景
文章插图
?年轻代 老年代 堆空间结构
为什么要这么设计呢?为什么要分那么多不同的内存区域干嘛?这是由对象的生命周期特征、与各类垃圾回收算法的优缺点所决定的,这正式垃圾回收器设计的理论基础 。经过统计分析,大多数应用程序对象生命周期符合两个特征:
垃圾回收的理论基础
- 绝大多数的对象都是“朝生夕灭”的,既创建不久即可消亡;
- 熬过越多此垃圾回收过程的对象就越难以消亡;
一块独立的内存区域只能使用一种回收算法,根据对象生命周期特征,将其划分到不同的区域,再对特定区域使用特定的垃圾回收算法,只有这样才能将垃圾算法的优点发挥到极致,这种组合的垃圾回收算法叫:分代垃圾算法 。。比如:在新生代使用标记-复制算法,在老年代使用标记-整理算法 。五、堆内存回收过程详解我们分析了如何判断对象是否可回收,还有3中基础的垃圾回收算法,以及年轻代、老年代的内存区域划分与原因 。接下来我们就一步一步来分析堆内存的回收流程 。
5.1 内存初始状态假设在第一垃圾回收之前,内存中的状态如图所示,Eden区有2个存活对象,3个垃圾对象,内存的可用区域已经所剩无几,Survivor区因为还没有进行任何MinorGC所以是空的,有1个大对象直接分配到了老年代,
文章插图
垃圾回收初始状态
5.2 第1次执行MinorGC后状态当新的对象分配到Eden区,发现内存空间不够,于是触发第一次MinorGC,垃圾回收器首先将Edne区中的两个存活对象复制到S0区,然后在清空Eden区的空间,如下图:
文章插图
?第一次MinorGC内存状态
5.3 程序运行一段时间后状态经过第1次MinorGC程序再运行一段时间后,堆内存状态如下:Eden区又产生了大量的对象,并且大部分对象都可回收状态,这也符合对象“朝生夕灭”的特征,S0区中也有1个对象可以回收,S1与老年代没有变化,在这种状态下,如果新对象分配再次触发MinorGC会发生什么呢?
推荐阅读
- 淘宝会被店家屏蔽吗 淘宝店铺被屏蔽了别人还能购买你的东西吗
- 硬盘有坏道就不行用了吗?别再吃哑巴亏了,今日跟大家再说一次
- 求职|27岁的宝妈求职被拒,映射出的是年龄歧视,还是“宝妈”身份?
- 央视|央视网评电信网络诈骗:你比你妈更容易被骗
- 肉桂茶怎么泡?简单几步享美味
- 风流茶说合,什么是玉米须茶
- 招聘|传说中的「职场黑名单」,到底长啥样
- 说说婴儿吃糖丸后的不良反应
- 轻度宫颈糜烂用药的方法有哪些
- 小儿清咽颗粒的使用说明书