Scavenge:基于copy的垃圾回收算法

76 阅读2分钟

基于 copy 的 GC 算法最早是在 1963 年,由 Marvin Minsky 提出来的。这个算法的基本思想是把某个空间里的活跃对象复制到其他空间,把原来的空间全部清空,这就相当于是把活跃的对象从一个空间搬到新的空间。因为这种复制具有方向性,所以我们把原空间称为 From 空间,把新的目标空间称为 To 空间。

分配新的对象都是在 From 空间中,所以 From 空间也被称为分配空间(Allocation Space),而 To 空间则相应地被称为幸存者空间(Survivor Sapce)。

要想识别一个对象是不是垃圾,Tracing 首先需要找到“根”引用集合。所谓根引用指的是不在堆中,但指向堆中的引用。根引用包括了栈上的引用、全局变量、JVM 中的 Handler、synchronized 对象等。它的基本思想是把对象之间的引用关系构成一张图,这样我们就可以从根出发,开始对图进行遍历。能够遍历到的对象,是存在被引用的情况的对象,就是活跃对象;不能被访问到的,就是垃圾对象。

深度优先搜索的非递归写法需要占用额外的空间,但有利于提高业务线程运行期的缓存命中率。而广度优先搜索则与其相反,它不利于运行期的缓存命中,但算法的执行效率更高。JDK6 以前的 JVM 使用了广度优先的非递归遍历,而在 JDK8 以后,已经把广度优先算法改为深度优先了,尽管这样做需要额外引用一个独立的栈。

Hotspot 的内存管理器在 Eden 空间中分配新的对象,每次 GC 时,如果将 S0 做为 To 空间,则 S1 与 Eden 合起来成为 From 空间。也就是说 To 空间这个空闲区域就大大减小了,这样可以提升空间的总体利用率。


此文章为7月Day20学习笔记,内容来源于极客时间《编程高手必学的内存知识》