3

我知道在 Java 中我们有软引用的概念。如果:

1)有一个软引用“sf”指的是一个对象A

2)在对象A中,有强引用指向对象B

3) 对象 A 和 B 未在其他任何地方引用。

根据定义,对象 A 和对象 B 都是“可轻松访问的”,对吗?

然后说我们现在内存快用完了,GC就开始了。GC是否有可能回收对象B而不回收对象A?

如果是这样的话,以后如果我们想通过“sf”访问对象B,它将为null。java如何避免这种情况发生?

我在 java doc 中没有看到任何解释。

4

3 回答 3

6

然后说我们现在内存快用完了,GC就开始了。GC是否有可能回收对象B而不回收对象A?

不会。GC 不会破坏可访问对象中的强引用。(作为回收过程的一部分,它当然会破坏无法访问的对象中的引用。但是您无法观察到这种情况的发生……因为要观察它,您需要该对象仍然可以访问。)

这是包的 javadoc 中此语句的结果java.lang.ref

“最后,当一个对象无法通过上述任何方式到达时,它是无法访问的,因此有资格进行回收。”

...其中“上述方式”包括强、软、弱和幻影可达性。

两个突出显示的词表示回收资格是处于无法到达状态的结果。由于其他州都没有提到回收资格,我们得出结论,不可到达性是回收的先决条件。

这当然符合常识。如果(假设地)允许 GC 将可访问对象中的强引用“清空”,则应用程序将不可能在对象进入此状态后安全地使用它们。(考虑空引用在库类的实例中的情况......)

于 2012-05-14T23:39:19.443 回答
2

我认为关于跟踪 GC 的基本工作原理的简短介绍应该可以澄清问题。

跟踪 GC(Java 和 .NET 中使用的都属于该类别)有一组所谓的 GC root pointers,它们是全局变量(在 java 中表示类的静态变量)和堆栈帧中的所有活动变量。GC 遍历这些对象并标记所有活动的对象,即可以通过来自至少一个根指针的引用到达。完成后,所有活动变量都已被标记,其余的可以被垃圾收集。

现在可以通过两种不同的方式处理软引用:a)我们遵循软引用并标记其中的所有对象,或者 b)我们不这样做。究竟发生了什么取决于给定的 JVM 实现,但在确定之后就没有其他区别了。

因此有两种可能的情况:

  • GC 遵循对 A 的软引用,在这种情况下,两个对象都不会被 GC。
  • GC 不遵循对 A 的软引用(并且没有对它的硬引用)。A 是 GCed,B 是 GCed 如果没有活动对象引用它。
于 2012-05-15T00:18:08.480 回答
1

从文档:

“如果一个对象不是强可达但可以通过遍历软引用来达到,那么它就是软可达的。”

“如果某个对象可以在不遍历任何引用对象的情况下被某个线程访问,则该对象是强可达的”

我认为那很清楚。B 是软可达的,因为它只能通过遍历软引用来达到。

说文档

于 2012-05-14T23:51:26.220 回答