3

这是一个面试问题,但我不太确定正确答案。假设我们有一些类,例如:

public class A {
    public Object link;
    public A() {
        link = null;
    }
}

然后我们创建两个实例:

A a1 = new A();
A a2 = new A();
a1.link = a2;
a2.link = a1;

然后我们发布引用:

a1 = null;
a2 = null;

那么问题来了:因为JVM会使用GC机制。它将如何处理这种情况?它会在运行时立即删除这两个实例,还是只对内存空间进行签名并将它们单独放置?如果我有 100 万个这样的实例形成一个循环并且没有外部引用怎么办?清理会让GC线程挂起吗?

4

3 回答 3

3

对象本身可以通过任意数量的链接(您提到的一百万个循环)相互引用。如果没有返回线程的“路由”,则对象有资格进行垃圾收集,无论它们连接到多少其他符合垃圾条件的节点。

现在这并不意味着他们会被收集,只是他们有资格。因此,如果您的垃圾收集器决定不处理它们,那么我想这可能被认为是内存泄漏。你不能保证它们会消失。

于 2012-11-28T03:43:10.550 回答
2

对于某些垃圾收集策略(例如引用计数)的幼稚实现,循环引用可能会导致内存泄漏。(这并不是说引用计数是幼稚的,而是说糟糕的实现可能会遇到这个问题。)

但是,这个问题对于实施 GC 的人来说是众所周知的,并且可以避免。此外,大多数现代 JVM 使用分代垃圾收集器,它们通常不会遇到此类问题。

于 2012-11-28T03:42:47.647 回答
0

根据代码的当前逻辑,a1 有一个指向 a2 的成员变量,而 a2 有一个指向 a1 的 ha 成员变量。当您执行 a1 = null a1 时,就有资格获得 GCed。a2 也是如此。现在,当 GC 运行时,它会尝试查看从根目录开始可以访问的所有对象,即使这两个相互引用,它们也会从根目录开始在链中变得不可访问(隔离情况),因此它们会毫无问题地进行垃圾收集。

于 2012-11-28T03:48:01.993 回答