19

我最近遇到了一段带有 WeakReferences 的 Java 代码——虽然我在介绍它们时遇到过它们,但我从未见过它们部署。这是应该经常使用的东西还是只有在遇到内存问题时才应该使用?如果是后者,它们是否可以轻松改造,或者代码是否需要认真重构?一般的 Java(或 C#)程序员可以忽略它们吗?

编辑过度热情地使用 WR 会造成任何损害吗?

4

4 回答 4

25

弱引用都是关于垃圾收集的。一个标准对象在所有对它的引用都被切断之前不会“消失”,这意味着在垃圾收集将其视为垃圾之前,必须删除您的各种对象对它的所有引用。

仅仅因为您的对象被其他对象引用而使用弱引用并不一定意味着它不是垃圾。它仍然可以被 GC 拾取并从内存中删除。

一个例子:如果我的应用程序中有一堆 Foo 对象,我可能想使用一个 Set 来保持我周围所有 Foo 的中央记录。但是,当我的应用程序的其他部分通过删除对 Foo 对象的所有引用来删除它时,我不希望我的 Set 持有该对象的剩余引用来防止它被垃圾收集!真的,我只是想让它从我的场景中消失。在这里您可以使用类似 Weak Set(Java 有 WeakHashMap)之类的东西,它使用对其成员的弱引用而不是“强”引用。

如果您的对象没有在您希望的时候被垃圾收集,那么您在簿记中犯了一个错误,有些东西仍然持有您忘记删除的引用。使用弱引用可以减轻这种簿记的痛苦,因为您不必担心它们会保持对象“活着”并且不会被垃圾收集,但您不必使用它们。

于 2009-10-29T00:25:43.513 回答
17

每当你想引用一个对象而不让对象自己保持活动时,你就可以使用它们。对于许多类似缓存的功能来说都是如此,但在事件处理中也起着重要作用,在这种情况下,订阅者不应通过订阅事件来保持活动状态。

一个小例子:刷新一些数据的定时器事件。任何数量的对象都可以订阅计时器以获得通知,但他们订阅计时器的事实不应该让它们保持活动状态。所以计时器应该对对象有弱引用。

于 2009-10-29T00:08:51.437 回答
10

过度使用 WR 会造成任何损害吗?

是的,它可以。

一个问题是弱引用会使您的代码更加复杂并且可能容易出错。任何使用弱引用的代码都需要处理每次使用时引用都被破坏的可能性。如果你过度使用弱引用,你最终会编写大量额外的代码。(您可以通过将每个弱引用隐藏在负责检查的方法后面来缓解这种情况,并按需重新创建丢弃的对象。但这可能不一定那么简单;例如,如果重新创建过程涉及网络访问,您需要应对重新创建失败的可能性。)

第二个问题是使用弱引用会产生运行时开销。明显的成本是创建弱引用并调用get它们的成本。一个不太明显的成本是每次 GC 运行时都需要做大量的额外工作。

最后一个问题是,如果您对应用程序将来很可能需要的东西使用弱引用,您可能会承担重复重新创建它的成本。如果这个成本很高(在 CPU 时间、IO 带宽、网络流量等方面),您的应用程序可能会因此表现不佳。给 JVM 更多内存而不使用弱引用可能会更好。

当然,这并不意味着您应该完全避免使用弱引用。只是你需要仔细考虑。也许您应该首先在您的应用程序上运行内存分析器,以找出内存使用问题的根源。

于 2009-10-29T00:47:52.950 回答
1

考虑使用 Wea​​kReference 时要问的一个好问题是,如果在对象不存在强引用的那一刻,弱引用无效,会有什么感觉。如果这会使 WeakReference 的用处降低,那么 WeakReference 可能不是最好的使用方法。如果这将是对来自垃圾收集的非确定性失效的改进,那么 WeakReference 可能是正确的选择。

于 2011-02-19T00:10:25.567 回答