我最近遇到了一段带有WeakReferences的Java代码 - 我从未见过它们已经部署过,虽然我们在介绍时遇到过它们。这是应该常规使用的东西还是只有在遇到内存问题时?如果是后者,它们是否可以轻松改装或代码是否需要严格的重构?普通的Java(或C#)程序员通常会忽略它们吗?
编辑过度热情使用WR可以造成任何损害吗?
答案 0 :(得分:21)
弱引用都是关于垃圾收集。 标准对象在所有对它的引用都被切断之前不会“消失”,这意味着在垃圾收集将其视为垃圾之前,必须删除各种对象所需的所有引用。
弱引用只是因为你的对象被其他对象引用并不一定意味着它不是垃圾。它仍然可以被GC拾取并从内存中删除。
一个例子:如果我的应用程序中有一堆Foo对象,我可能想使用Set来保存我所拥有的所有Foo的中心记录。但是,当我的应用程序的其他部分通过删除对它的所有引用来删除Foo对象时,我不希望我的Set的剩余引用保留到该对象以防止它被垃圾收集!真的,我只是希望它从我的集合中消失。这就是你使用Weak Set(Java有一个WeakHashMap)之类的东西,它使用对其成员的弱引用而不是“强”引用。
如果您的对象在您想要它们时没有被垃圾收集,那么您在簿记中出错了,某些内容仍然存在您忘记删除的引用。使用弱引用可以减轻这种簿记的痛苦,因为您不必担心它们保持对象“活着”并且没有垃圾收集,但是您没有使用来使用它们。
答案 1 :(得分:16)
只要您想要对对象进行引用而不自己保持对象存活,就可以使用它们。这对于许多类似缓存的功能来说都是如此,但在事件处理中也发挥了重要作用,订阅者不应通过订阅事件来保持活着。
一个小例子:一个刷新某些数据的计时器事件。任何数量的对象都可以在计时器上订阅以获得通知,但是他们在计时器上订阅的这个事实不应该使它们保持活动状态。所以计时器应该对对象有弱引用。
答案 2 :(得分:8)
可以造成任何伤害 过度热心使用WR?
是的,可以。
一个问题是弱引用会使您的代码更复杂并且可能容易出错。任何使用弱引用的代码都需要处理每次使用它时引用被破坏的可能性。如果过度使用弱引用,最终会编写大量额外代码。 (您可以通过隐藏负责检查的方法后面的每个弱引用来缓解这种情况,并根据需要重新创建丢弃的对象。但这可能不一定那么简单;例如,如果重新创建过程涉及网络访问,你需要应对重新创建失败的可能性。)
第二个问题是使用弱引用存在运行时开销。显而易见的成本是创建弱引用并在其上调用get
。不太明显的成本是每次GC运行时都需要做大量的额外工作。
最后一个问题是,如果您对应用程序很可能在将来需要的某些内容使用弱引用,则可能会产生重复重新创建它的成本。如果此成本很高(就CPU时间,IO带宽,网络流量而言),您的应用程序可能会因此而表现不佳。你可能最好给JVM更多的内存,而不是使用弱引用。
当然,这并不意味着你应该完全避免使用弱引用。只是你需要仔细思考。也许您应该首先在应用程序上运行内存分析器,以确定内存使用问题源于何处。
答案 3 :(得分:1)
在考虑使用WeakReference时要问的一个很好的问题是,如果弱引用在对象存在的强引用中无效,人们会感觉如何。如果这会使WeakReference不那么有用,那么WeakReference可能不是最好用的。如果这比垃圾收集的非确定性失效更好,那么WeakReference可能是正确的选择。