3

让我们考虑以下 2 个循环引用示例:

直接循环参考

class A {        
    B b;        
}

class B {
    A a;
}

弱引用

class A {
    B b;
}

class B {
    WeakReference<A> aRef;
}

@Jon Skeet回答的以下SO 问题清楚地表明,只要循环中不存在来自已知根的“GC walk”,直接示例也将被垃圾收集。

我的问题如下:

是否有任何理由使用或不使用示例 2 中表示的习语 - 使用 Wea​​kReference 的习语?

4

2 回答 2

7

是否有任何理由执行或以其他方式使用或不使用示例 2 中表示的习语

JavaReference类型有几个性能影响:

  • 它们比常规引用使用更多空间。

  • 与普通引用相比,它们对垃圾收集器的工作要多得多。

  • 我也相信它们会导致对象的收集被一个或多个 GC 周期延迟......取决于 GC 实现。

此外,应用程序必须处理 aWeakReference可能被破坏的可能性

相比之下,当您在第一个示例中使用普通循环引用时,它们没有性能或空间开销。

总而言之,您的弱引用习惯用法会降低性能并增加程序复杂性......我看不到任何切实的好处。


我的猜测是,这个问题源于错误的观念,即循环引用比 Java 中的非循环引用更昂贵......或者它们在某种程度上存在问题。(还有什么其他合乎逻辑的原因会导致人们提出这样的“成语”?)事实上,情况并非如此。Java 垃圾收集器不受引用计数问题的困扰;例如 C++“智能指针”。循环引用在 Java 中被正确处理(即没有内存泄漏)并且有效。

于 2013-09-16T07:29:40.577 回答
1

问题是你不知道 GC 什么时候会清除弱引用对象。

它可能会在您声明时被清除!GC非常渴望收集它。

或者您可以对弱引用对象进行根引用,以防止它被垃圾收集。

或者通过RegisteredQueue查看它的状态。

这就像 finalize 方法。你不知道 GC 什么时候会执行这个方法。

资料来源:

http://pawlan.com/monica/articles/refobjs/ http://docs.oracle.com/javase/7/docs/api/java/lang/ref/WeakReference.html

于 2013-09-16T07:53:08.707 回答