垃圾回收器如何工作

关于效率(P89-90)

在以前使用过的程序语言中,在堆上分配对象的代价十分高昂。然而,垃圾回收器对于提高对象的创建速度,却有明显的效果。

垃圾回收站工作时,将一面回收空间,一面使堆中的对象紧凑排列,这样“堆指针”就可以很容易移动到更靠近传送带的开始处,也就尽量避免了页面错误。通过垃圾回收器对对象重新排列,实现了一种高速的、有无限空间可供分配的堆模型。

(页面错误,即访问了不存在的内存空间。)

在堆栈中,堆栈指针向下移动,则分配新的内存,向上移动则释放那些内存。这是仅次于寄存器的快速有效的分配存储的方法。(P22)

可达性分析算法(P90)

对任何"活"的对象,一定能最终追溯到其存活在堆栈或静态存储区之中的引用。这个引用链条可能会穿过数个对象层次。由此,如果从堆栈和静态存储区开始,遍历所有的引用,就能找到“活”的对象。对于发现的每个引用,必须追踪它所引用的对象,然后是此对象包含的所有引用,如此反复进行,直到“根源于堆栈和静态存储区的引用”所形成的网络全部被访问为止。

复制(P91)

在Thinking in Java这本书中(基于Java5)讨论的虚拟机,内存分配较大的“块”为单位。如果对象较大,它会占用单独的块。

严格来说,“停止-复制”要求在释放旧有对象之前,必须先把所有存活对象从旧堆复制到新堆,这将导致大量内存复制行为。有了块之后,垃圾回收器在回收的时候就可以往废弃的块里拷贝对象了。

每个块都用相应的代数来记录它是否还存活。通常,如果块在某处被引用,其代数会增加;垃圾回收器将对上次回收动作之后新分配的块进行整理,这对处理大量短命的临时对象很有帮助。垃圾回收器会定期进行完整的清理动作——大型对象仍然不会被复制(只是其代数会增加),内含小型对象的那些块则被复制并整理。

Last updated