《垃圾回收的算法与实现》——GC复制算法

基本概念

  • GC复制算法将堆分红From和To两个内存块,当From被占满时GC将From中的存活对象复制到To中,同时将From和To交换。
  • 经过递归遍历GC root(即采用深度优先)复制存活对象,对于已经复制过的标记其COPIED字段。
  • 复制过的对象将在From的对象的forwarding记录To中该对象地址,以便于其他引用了该对象的引用进行修改。
  • 分配对象时将先判断From中连续可用空间是否够用(复制算法不存在碎片),若是不够则进行一次GC,还不够则分配失败。

优缺点

优势

  1. 吞吐量大,只须要遍历一次From空间Sweep须要遍历两次,并且只复制存活的对象。
  2. 高速分配,不须要经过空闲链表直接在连续的内存上进行分配。
  3. 没有碎片。
  4. 与缓存兼容,复制存活对象时采用深度优先算法使相关联的对象都在附近。

缺点

  1. 堆的使用效率低,必须分配一个To,其不能分配对象。
  2. 不兼容保守式GC算法,须要移动对象。
  3. 递归调用,复制对象的深度优先算法是经过递归调用实现的,递归将消耗栈等资源。

改进

Cheney的GC复制算法

针对递归算法

  • 复制算法的To中增长scan指针,其指向To中已经复制过全部子对象位置。
  • 首先将GC root直接引用的对象复制到To中,然后经过scan指针的移动对后续存活对象进行复制。实现了广度优先搜索算法
  • 经过scan在To中的移动实现了一个隐式的FIFO队列。
  • 取消COPIED字段,经过forwarding字段是否指向To区间来判断该对象是否已被复制。
  • 优势在于取消了递归,缺点则是采用了广度优先算法使其与缓存不兼容。

近深度优先搜索方法

针对Cheney的复制算法中与缓存不兼容问题数组

  • page:堆分隔成一个个页面的数组;local_scanf:每一个页中搜索用的指针做为元素的数组;major_scan:指向未搜索完的页面开头;free:分块开头;
  • 第一阶段从GC root中将其直接引用复制到第一个页中。
  • 然后对每一个对象按照相似深度优先算法,区别在于其原始深度优先算法每层一次只搜索一个对象而该算法则将同一层一次搜索完 此处没懂,还有页占满的问题

多空间复制算法

针对堆利用率低缓存

  • 将堆分红多份,每次取其中的两个分别做为From和To,其他则采用Mark-Sweep算法。
  • From总在To的右边的块中,每执行一次GC,From和To均向右移动一个块。
  • 在GC时先进行标记阶段,当存活对象处于From时执行copy,当处于其他块时执行mark。
  • 优势在于提升了堆的利用率,缺点则是引入了Mark-Sweep算法致使STW时间变长,分块得采用空闲链表