这可能是一个愚蠢的问题 当一个对象被标记为垃圾收集时,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?
}
}
答案 0 :(得分:5)
是的,如果仅 ContainerClass
对象有对它们的引用,那么ContainedClass
对象将在ContainerClass
的同一时间符合垃圾回收的条件对象本身符合条件。
请注意,这些对象的实际集合可以独立发生。
答案 1 :(得分:3)
你的问题在某种程度上是回到前面的。对象未标记为要收集,而是标记为保留。
垃圾收集器标记仍在使用的对象,从活动堆栈帧和所有静态变量等开始,跟随它找到的引用。垃圾收集器找到的每个对象都被标记为正在使用中,不会被收集。
因此,子对象没有标记为集合,而是因为它们的父对象不是标记的,所以它们没有标记为保留。
(Mark和Sweep垃圾收集器肯定是这样,这是大多数JVM的默认设置。其他垃圾收集器可能表现不同。)
答案 2 :(得分:1)
如果没有直接或间接持有对象引用的活动线程,则对象已准备好进行垃圾回收。所以是的,所包含的对象也准备好被垃圾收集。
答案 3 :(得分:0)
对于您的特殊示例:是的,包含的对象将标记为gc,但不会,因为收集了容器。它们被标记为在容器消失之后,没有其他对象拥有对ContainedClass
实例的引用。
所以一般来说,不,它不是递归的。如果可以收集每个实例,则单独测试每个实例。 包含的实例不是容器类的一部分,它们过着自己的生活。容器只是持有某种指针。
答案 4 :(得分:0)
java是否递归执行GC?
没有。一个体面的垃圾收集器不使用简单的递归进行标记。如果是这样,那么标记长链表将要求标记算法使用非常深的堆栈来标记它。这将是一个重大问题。
GC实现者可以使用许多策略来避免过度递归:
next
字段。如果你想了解更多细节,请参阅理查德·琼斯和拉斐尔·林斯的"Garbage Collection: Algorithms for Automatic Dynamic Memory Management",1996年。(理查德·琼斯,安东尼·霍斯金和艾略特·莫斯出版了一本名为"The Garbage Collection Handbook: The Art of Automatic Memory Management"的新书。年!!)
(Nit pick:GC没有标记垃圾收集的对象。它将它们标记为非垃圾......并丢弃未标记的对象。)