垃圾回收的算法

来源:互联网 发布:快鱼服饰网络专卖店 编辑:程序博客网 时间:2024/05/01 03:53

垃圾回收有3种典型方法:引用计数、标记并清除,以及复制。

1 引用计数

在引用计数中,每一块动态分配的内存都与一个引用计数相关。这个计数在每次对内存的引用增加的时候增1,在取消对内存的引用时减1。用C++的术语来说,这意味着每次将一个指针指向一块已分配内存的时候,与内存相关的引用计数增1。当这个指针指向其他位置的时候,引用计数减1。当引用计数下降为0的时候,内存不再被使用,从而可以释放。

引用计数的最大优点是其简单性—— 易于理解并实现。另外,它的位置不受堆结构的影响,因为引用计数不依赖于对象的物理位置。引用计数增加了每个指针操作的开销,但是回收阶段的开销相对较低。其主要的缺点是循环的引用阻止了其他不再使用的内存的释放。当两个对象互相指向对方的时候(无论是直接的还是间接的),就会发生循环引用。在此情况下,对象的引用计数永不为0。为了解决循环引用的问题,设计了一些解决方案,但是这些方案都会增加复杂程度和/或开销。

2 标记并清除

标记并清除涉及到两个阶段。在第一个阶段,堆中的所有对象都被设置为未标记状态。然后,可以由程序变量直接或者间接访问的所有对象都被标记为“正在使用”。在第二个阶段,扫描所有已分配的内存(也就是说,进行了内存的清除),会释放所有未标记的元素。

标记并清除有两个主要优点。首先,它很容易处理循环引用。其次,在回收之前,它实际上没有增加运行时开销。它也有两个主要缺点。首先,由于在回收的时候必须扫描整个堆,因此回收垃圾可能会花费较多的时间。因此,对于某些程序,垃圾回收可能会导致程序运行效率低下。其次,尽管标记并清除在概念上很简单,但是要有效地实现它并非易事。

3 复制

复制算法将自由内存分到两个空间中。一个是活动空间(持有当前的堆),一个是空闲空间。在垃圾回收期间,活动空间中正在使用的对象被确认,并复制到空闲空间中。然后,两个空间的角色反转,空闲空间变为活动空间,活动空间变为空闲空间。复制提供了复制过程中压缩堆的优点。它的缺点是在某个时刻只允许使用一半的自由内存。