1. Overview
1.概述
In this article, we’ll have a look at the concept of a weak reference – in the Java language.
在这篇文章中,我们将看一下弱引用的概念–在Java语言中。
We’re going to explain what these are, what they’re used for, and how to work with them properly.
我们将解释这些是什么,它们的用途是什么,以及如何正确使用它们。
2. Weak References
2.薄弱的参考资料
A weakly referenced object is cleared by the Garbage Collector when it’s weakly reachable.
当一个弱引用的对象是弱可及的时候,它就会被垃圾收集器清除掉。
Weak reachability means that an object has neither strong nor soft references pointing to it. The object can be reached only by traversing a weak reference.
弱可及性是指对象既没有强引用也没有软引用指向它。只有通过遍历弱引用才能到达该对象。
First off, the Garbage Collector clears a weak reference, so the referent is no longer accessible. Then the reference is placed in a reference queue (if any associated exists) where we can obtain it from.
首先,垃圾收集器会清除一个弱引用,所以该引用不再可以被访问。然后,该引用被放置在一个引用队列中(如果有任何相关的存在),我们可以从那里获得它。
At the same time, formerly weakly-reachable objects are going to be finalized.
同时,以前可触及的薄弱对象也将被最终确定。
2.1. Weak vs Soft References
2.1.弱引用与软引用
Sometimes the difference between weak and soft references is unclear. Soft references are basically a big LRU cache. That is, we use soft references when the referent has a good chance of being reused in the near future.
有时,弱引用和软引用之间的区别并不清楚。软引用基本上是一个大的LRU缓存。也就是说,当引用者在不久的将来有很大的机会被重用时,我们就使用软引用。
Since a soft reference acts as a cache, it may continue to be reachable even if the referent itself is not. As a matter of fact, a soft reference is eligible for collection if and only if:
由于软引用充当了缓存的角色,即使引用者本身不在了,它也可以继续被访问。事实上,当且仅当一个软引用有资格被收集。
- The referent is not strongly reachable
- The soft reference is not being accessed recently
So a soft reference may be available for minutes or even hours after the referent becomes unreachable. On the other hand, a weak reference will be available only for as long as its referent is still around.
因此,一个软参考可能在参考者变得无法联系的几分钟甚至几个小时内都是可用的。另一方面,一个弱的参照物只在其参照物仍然存在的情况下才可用。
3. Use Cases
3.使用案例
As stated by Java documentation, weak references are most often used to implement canonicalizing mappings. A mapping is called canonicalized if it holds only one instance of a particular value. Rather than creating a new object, it looks up the existing one in the mapping and uses it.
正如Java文档中所说,弱引用最常被用来实现规范化映射。如果一个映射只持有一个特定值的实例,那么它就被称为规范化映射。它不是创建一个新的对象,而是在映射中查找现有的对象并使用它。
Of course, the most known use of these references is the WeakHashMap class. It’s the implementation of the Map interface where every key is stored as a weak reference to the given key. When the Garbage Collector removes a key, the entity associated with this key is deleted as well.
当然,这些引用最著名的用途是WeakHashMap类。它是Map接口的实现,每个键都被存储为给定键的弱引用。当垃圾收集器删除一个键时,与这个键相关的实体也被删除。
For more information, check out our guide to WeakHashMap.
欲了解更多信息,请查看我们对WeakHashMap的指南。
Another area where they can be used is the Lapsed Listener problem.
另一个可以使用它们的领域是失效听众问题。
A publisher (or a subject) holds strong references to all subscribers (or listeners) to notify them about events that happened. The problem arises when a listener can’t successfully unsubscribe from a publisher.
一个发布者(或一个主体)持有对所有订阅者(或听众)的强引用,以通知他们发生的事件。当听众不能成功地从发布者那里取消订阅时,问题就出现了。。
Therefore, a listener can’t be garbage collected since a strong reference to it’s still available to a publisher. Consequently, memory leaks may happen.
因此,一个监听器不能被垃圾回收,因为它的强引用对发布者来说仍然可用。因此,可能会发生内存泄漏。
The solution to the problem can be a subject holding a weak reference to an observer allowing the former to be garbage collected without the need to be unsubscribed (note that this isn’t a complete solution, and it introduces some other issues which aren’t covered here).
解决这个问题的方法可以是主体持有对观察者的弱引用,允许前者被垃圾回收,而不需要取消订阅(注意这不是一个完整的解决方案,它还引入了一些其他问题,这里没有涉及)。
4. Working With Weak References
4.与薄弱的参考资料合作
Weak references are represented by the java.lang.ref.WeakReference class. We can initialize it by passing a referent as a parameter. Optionally, we can provide a java.lang.ref.ReferenceQueue:
弱引用是由java.lang.ref.WeakReference类来表示。我们可以通过传递一个参照物作为参数来初始化它。另外,我们可以提供一个java.lang.ref.ReferenceQueue。
Object referent = new Object();
ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();
WeakReference weakReference1 = new WeakReference<>(referent);
WeakReference weakReference2 = new WeakReference<>(referent, referenceQueue);
The referent of a reference can be fetched by the get method, and removed manually using the clear method:
可以通过get方法获取引用的引用,并通过clear方法手动删除。
Object referent2 = weakReference1.get();
weakReference1.clear();
The pattern for safe working with this kind of references is the same as with soft references:
安全使用这种引用的模式与soft references相同。
Object referent3 = weakReference2.get();
if (referent3 != null) {
// GC hasn't removed the instance yet
} else {
// GC has cleared the instance
}
5. Conclusion
5.结论
In this quick tutorial, we had a look at the low-level concept of a weak reference in Java – and focused on the most common scenarios to use these.
在这个快速教程中,我们看了一下Java中弱引用的低级概念–并着重介绍了使用这些弱引用的最常见的情况。