10

在目标 C 中,两个不同的引用有可能相互指向。

但这在 Java 中可能吗?我的意思是,两个对象引用可以相互指向吗?如果可能的话,它们什么时候会被垃圾收集?

而且,在嵌套类的情况下,两个对象(内部类和外部类)相互链接——这些对象是如何被垃圾收集的?

4

3 回答 3

34

我假设您在谈论循环引用。如果无法通过从 GC 根开始的链访问对象,Java 的 GC 会将其视为“垃圾”。即使对象可能相互指向形成一个循环,如果从根中切断它们仍然有资格进行 GC。

Java中有四种GC根:

  1. 局部变量由线程的堆栈保持活动状态。这不是真实的对象虚拟参考,因此不可见。出于所有意图和目的,局部变量是 GC 根。

  2. 活动 Java 线程始终被视为活动对象,因此是 GC 根。这对于线程局部变量尤其重要。

  3. 静态变量由它们的类引用。这一事实使它们成为事实上的 GC 根源。类本身可以被垃圾收集,这将删除所有引用的静态变量。当我们通常使用应用程序服务器、OSGi 容器或类加载器时,这一点特别重要。

  4. JNI 引用是本机代码作为 JNI 调用的一部分创建的 Java 对象。这样创建的对象会被特殊处理,因为 JVM 不知道它是否被本机代码引用。这样的对象代表了一种非常特殊形式的 GC 根。

您也可以在此处阅读以获取更多信息。

在此处输入图像描述

于 2013-07-11T07:08:57.127 回答
7

是的,你可以这样做。像这样:

class Pointy {
    public Pointy other;
}

Pointy one = new Pointy();
Pointy two = new Pointy();
one.other = two;
two.other = one;

当两个对象都没有被其他任何东西指向时,它们被垃圾收集,或者其他对象从当前运行的代码中“无法访问”。Java 垃圾收集器是“跟踪”垃圾收集器,这意味着它们可以发现此类问题。

相反,引用计数系统(如没有“现代”垃圾收集的 Objective C ——我不知道默认值是什么)通常无法检测到此类问题,因此对象可能会泄漏。

于 2013-07-11T07:12:50.783 回答
4

当然,您可以让对象相互引用。您可以简单地将this两个对象中的指针相互传递,这是完全有效的。

但是,这并不意味着仍然可以从 GC 根目录访问这些对象。把它想象成一棵(图)树。如果你从主干上切掉一个完整的分支,那么整个分支都会丢失,无论涉及多少对象或维护彼此的引用。

于 2013-07-11T07:12:05.350 回答