垃圾收集算法

14 篇文章 0 订阅

垃圾收集算法分为两大类:“引用计数式垃圾收集”与“追踪式垃圾收集” 也常被称为“直接垃圾收集”与“间接垃圾收集”两大类
本文主要讲追踪式垃圾收集

分代收集理论

大多数虚拟机都遵循了“分代收集”的理论进行设计 该理论建立在两个分代假说上

  1. 弱分代假说:绝大多数对象都是朝生夕灭的
  2. 强分代假说:熬过越多次垃圾收集过程的对象就越难以消亡

两个分代假说共同奠定了垃圾收集器的一致设计原则:收集器应该将java堆划分出不同的区域 然后将回收对象根据其年龄(即对象熬过垃圾收集过程的次数)分配到不同的区域中进行存储
这样如果一个区域大多数对象都是朝生夕灭的每次回收时只关注如何保留少量存活而不是去标记大量要被回收的对象 就能以较低代价回收大量空间
如果一个区域大部分是难以消亡的 能使用较低频率来回收该区域 同时兼顾了垃圾收集的时间开销和内存空间的有效利用
java堆划分不同的区域后 垃圾收集器才可以每次只回收其中一个或部分区域 一般至少将java堆划分为新生代和老年代两个区域(顾名思义) 每次垃圾收集后存活的少量对象将逐步晋升到老年代中存放
但是有一个明显的缺陷:对象不是孤立的 对象之间会存在跨代引用 若进行一次新生代区域的收集 但新生代中的对象被老年代引用 为了找到该区域的存活对象 需要在额外遍历整个老年代所有对象 此时需要对分代收集理论添加第三条法则0000000000000
3. 跨代引用假说:跨代引用相对于同代引用来说仅占极少数
根据该条假说 只需在新生代上建立一个全局的数据结构(记忆集) 这个结构把老年代划分为若干小块 标识出老年代的那一块内存存在跨代引用 这样在新生代收集时 只有包含了跨代引用的小块内存的对象才会被加入到GC Roots进行扫描

垃圾收集算法

针对不同区域安排与里面存储对象存亡特征相匹配的垃圾收集算法——“标记-复制算法” “标记-清除算法” “标记-整理算法”等

标记-清除算法最早出现的最基础的垃圾收集算法
分为“标记”与“清除”两个阶段 :首先标记出所有需要回收的对象 标记完成后统一回收调所有被标记的对象 也可以反过来 标记存活的对象 统一回收所有未被标记的对象 标记过程就是对象是否属于垃圾的过程
缺点

  1. 执行效率不稳定
  2. 内存空间碎片化问题 标记清除后会产生大量的不连续的内存碎片 碎片太多可能会导致当以后在程序运行过程中需要分配较大对象时无法找到足够的连续内存而不得不出发另一次垃圾收集

标记-复制算法解决了标记-清除算法面对大量可回收对象时执行效率低的问题
最初是一种“半区复制” 将内存划为大小相等的两块 每次只用一块 当内存用完了就将存活的对象复制到另一块 再清理上一块内存 这样就不用考虑空间碎片的复杂情况 缺陷:空间浪费了一半
后根据朝生夕灭的特点 新生代中对象有98%熬不过第一轮收集 不用按照1:1划分新生代内存空间 称为“Apple式回收
将新生代分为一块较大的Edan空间和两块较小的Survivor空间 每次分配内存只用Eden空间和一块Survivor空间 垃圾收集时 将其存活的对象一次性复制到另一块Survivor空间 然后清理其他空间 Hotspot虚拟机默认Eden和Survivor的大小比例是8:1 同时每次垃圾回收不能保证只有不多于10%的存活对象 此时就需要依赖其他内存区域(大多数是老年代)进行分配担保

标记-整理算法
标记-复制算法在对象存活率高的时候需要较多复制操作 效率会降低 更关键的是需要额外的空间进行分配担保 所以在老年代不能直接选用标记-复制算法
最初与标记-清除算法相似 只是标记后对存活对象进行移动 然后清理掉边界以外的内存 缺点:操作麻烦 并且进行移动时必须停止用户应用程序才行 但是相对于内存碎片化的清理还是更好的
一种解决方式:大多数采用标记-清除算法 到空间碎片化严重时使用标记-整理算法一次

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值