2008年9月5日星期五

JVM_005:GC 算法介绍(摘录+整理)

既然GC负责垃圾回收,那自然有一套回收的办法。所有的算法无外乎都做两件事:
(1)找到所有不再使用的对象。
(2)回收这些对象的空间。
目前已经有很多GC算法,除了Sun之外,还有Oracle、IBM、Symantec、Microsoft、HP以及各种开源组织都投入到这项研究。目前,有如下几种垃圾收集的基本策略:

1. 引用计数器
引用计数器保存在对象里,当一个对象被创建时,计数器为1。当其他对象引用这个对象时,该对象的引用计数器加1。当对这个对象的引用结束时,计数器减1。引用计数器为0时,则被看作是垃圾。该算法的缺点是没有遍历功能。该算法已经过时,不再过多介绍。

2. 遍历搜索器
搜索器从树结构的根节点开始遍历,寻找对象引用,并把被引用的对象做标记(Mark)。遍历之后,未作标记的对象被视为垃圾,可被GC回收(Sweep)。

3. 碎片整理器
Heap中的碎片是由于不断分配和释放造成的。如果不合并这些碎片,即使有足够的空间,但由于没有足够大的连续空间,也无法分配空间给对象。这时只好扩大Heap空间,造成空间利用率低,降低运行性能。
Heap 碎片整理(Compacting collector)有两个步骤,整理和拷贝。这两步用来移动Heap中的对象从而减少碎片。既然好移动对象的位置,当要也要更新对象的引用,但是更新对象引用是会降低VM的性能,因此建立一个对象句柄表,对象引用指向对象句柄,当对象移动时,更新对象的句柄,而不用改变对象引用的值。拷贝步骤就是将 Heap的对象移动到新的位置。为了提高拷贝的性能,VM被分为两个区,VM在内只能使用两个中的一个。当使用中的区没有空间后,将所有的对象从该空间拷贝到另一个空间,并继续在另一个空间工作,直到另一个空间满了为止,再把所有对象拷贝回原来的空间。该方法的代价就是需要花费2倍的空间。

4. 分代收集算法
Java 1.5 后,主要使用分代收集算法,详见《分代垃圾收集算法》。

有这么多的算法,该使用哪一种GC算法呢?
回答是取决于你的应用。不同的垃圾收集实现使用不同的策略来识别和收回不可到达的对象,它们与用户程序和调度器以不同的方式互动。不同类型的应用程序对于垃圾收集有不同的要求:实时应用程序会将要求收集暂停的持续时间短并且有限制;而企业应用程序可能允许更长时间和可预测性更低的暂停以获得更高的吞吐能力。

没有评论: