java是否递归执行GC?

时间:2011-06-14 08:58:24

标签: java garbage-collection

这可能是一个愚蠢的问题 当一个对象被标记为垃圾收集时,java是否也标记了所包含的垃圾收集对象?

我的意思是,

class ContainerClass {
    ContainedClass obj1, obj2;  
    //Constructor
    ContainerClass() {
    obj1 = new ContainedClass ();
    obj2 = new ContainedClass ();
    }
  // main
    public static void main( String args[]) {
        ContainerClass  c = new ContainerClass();
        c = null ; // c is mared for GC. The question is c.obj1 and c.obj2 is also marked?
    }   
}

5 个答案:

答案 0 :(得分:5)

是的,如果 ContainerClass对象有对它们的引用,那么ContainedClass对象将在ContainerClass的同一时间符合垃圾回收的条件对象本身符合条件。

请注意,这些对象的实际集合可以独立发生。

答案 1 :(得分:3)

你的问题在某种程度上是回到前面的。对象未标记为要收集,而是标记为保留。

垃圾收集器标记仍在使用的对象,从活动堆栈帧和所有静态变量等开始,跟随它找到的引用。垃圾收集器找到的每个对象都被标记为正在使用中,不会被收集。

因此,子对象没有标记为集合,而是因为它们的父对象不是标记的,所以它们没有标记为保留。

(Mark和Sweep垃圾收集器肯定是这样,这是大多数JVM的默认设置。其他垃圾收集器可能表现不同。)

答案 2 :(得分:1)

如果没有直接或间接持有对象引用的活动线程,则对象已准备好进行垃圾回收。所以是的,所包含的对象也准备好被垃圾收集。

答案 3 :(得分:0)

对于您的特殊示例:是的,包含的对象将标记为gc,但不会,因为收集了容器。它们被标记为容器消失之后,没有其他对象拥有对ContainedClass实例的引用。

所以一般来说,不,它不是递归的。如果可以收集每个实例,则单独测试每个实例。 包含的实例不是容器类的一部分,它们过着自己的生活。容器只是持有某种指针。

答案 4 :(得分:0)

  

java是否递归执行GC?

没有。一个体面的垃圾收集器不使用简单的递归进行标记。如果是这样,那么标记长链表将要求标记算法使用非常深的堆栈来标记它。这将是一个重大问题。

GC实现者可以使用许多策略来避免过度递归:

  • 您实际上并未使用递归。您使用标记堆栈和迭代算法......这样更节省空间。
  • 技巧可用于在遍历深度列表时最小化堆栈深度...如果您知道深度在哪里;例如这是next字段。
  • Knuth和Boehm-Demers-Weiser有办法处理溢出的标记堆栈,包括溢出堆栈然后拾起碎片。
  • Deutsch-Schorr-Waite算法使用指针反转,因此根本没有标记堆栈。
  • 等等。

如果你想了解更多细节,请参阅理查德·琼斯和拉斐尔·林斯的"Garbage Collection: Algorithms for Automatic Dynamic Memory Management",1996年。(理查德·琼斯,安东尼·霍斯金和艾略特·莫斯出版了一本名为"The Garbage Collection Handbook: The Art of Automatic Memory Management"的新书。年!!)

(Nit pick:GC没有标记垃圾收集的对象。它将它们标记为非垃圾......并丢弃未标记的对象。)