WeakHashMap 和强引用值

发布于 2025-01-03 09:48:12 字数 288 浏览 2 评论 0 原文

Javadocs 说“当一个键被丢弃时,它的条目就会有效从地图中删除”。

但除非有另一个线程偶尔删除此类 Map.Entry 条目,否则值对象不会被映射强引用吗?但由于没有这样的线程在运行,因此只有 get 方法调用可以删除此类条目 - 一次一个。

由于这个原因,我几乎总是使用 WeakHashMap>。为什么他们不将其作为默认行为 - 值也作为弱引用?

Javadocs says "When a key has been discarded its entry is effectively removed from the map".

But unless there is another thread that occasionally removes such Map.Entry entries, won't the value objects be strongly referenced by the map? But since there is no such thread running, only the get method invocations can remove such entries - one at a time.

I almost always use WeakHashMap<K, WeakReference<V>> for that reason. Why would they not have made that the default behavior - values as weak references too?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

原谅我要高飞 2025-01-10 09:48:12

引用队列用于自动删除条目。

http://docs.oracle.com /javase/1.4.2/docs/api/java/lang/ref/ReferenceQueue.html

引用队列,在检测到适当的可达性更改后,垃圾收集器将已注册的引用对象附加到该队列。

基本上,弱引用是垃圾收集器的核心部分,因此当发生 GC 扫描时,会找到未使用的引用并将其放入队列中,然后可以根据这些队列的内容采取操作。

线程可以位于队列的 remove 方法在需要完成清理或轮询队列时发出警报。

“Java 理论与实践:用弱引用堵塞内存泄漏” 解释:

WeakHashMap 的实现说明了弱引用的常见用法——某些内部对象扩展了 WeakReference

...

WeakHashMap 使用弱引用来保存映射键,这允许键对象在不再被应用程序使用时被垃圾回收,并且 get()实现可以通过 WeakReference.get() 是否返回 null 来区分活动映射和死映射。但这只是在应用程序的整个生命周期中防止 Map 内存消耗增加所需的一半;在收集关键对象后,还必须采取一些措施从 Map 中删除死条目。 否则,Map 将简单地填充与死键对应的条目。 虽然这对应用程序来说是不可见的,但它仍然可能导致应用程序内存不足,因为 Map.Entry 和值即使键被收集,对象也不会被收集。

...

引用队列是垃圾收集器向应用程序反馈有关对象生命周期的信息的主要方式。弱引用有两个构造函数:一个仅将引用对象作为参数,另一个也接受引用队列。当创建了具有关联引用队列的弱引用并且引用对象成为 GC 的候选者时,引用对象(而不是引用对象)在引用被清除后将排队到引用队列中。然后,应用程序可以从引用队列中检索引用,并获悉引用对象已被收集,以便它可以执行相关的清理活动,例如删除已从弱集合中删除的对象的条目。 (引用队列提供与 BlockingQueue 相同的出队模式——轮询、定时阻塞和不定时阻塞。)

编辑:

即使使用队列,弱映射仍然可能泄漏。 Ephemerons 试图解决弱密钥引用强保留值(该值引用该密钥)的情况。它们无法在 java 中实现。

Ephemerons 解决了尝试使用注册表将属性“附加”到对象时常见的问题。当某个属性应该附加到一个对象时,该属性(就 GC 行为而言)通常应该具有该对象的实例变量所具有的生命周期。然而,由于对象及其属性之间存在外部关联,这会变得复杂,例如:

属性---------注册表---------关联---------对象

在这里,注册表(第三方)将保留关联本身,这需要从注册表中手动删除(而不是自动垃圾收集)。虽然这个问题总是可以在任何给定的具体情况下通过使用各种弱关联类型之一来解决,但选择“正确”的关联类型取决于多种因素,其中一些因素可以动态变化。

星历通过定义星历的“内容”(值)将被严格保留,直到已知密钥被垃圾收集为止,从而解决了这个问题。从此以后,星历的内容将被弱化。因此,当且仅当键是可垃圾收集的时,星历的内容才可以进行垃圾收集,这正是我们在对象的实例变量中观察到的行为。

Reference queues are used to automatically remove entries.

http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/ref/ReferenceQueue.html

Reference queues, to which registered reference objects are appended by the garbage collector after the appropriate reachability changes are detected.

Basically, weak references are a core part of the garbage collector, so when a GC sweep happens, unused references are found and put onto queues and then action can be taken based on the content of those queues.

A thread can sit on the queue's remove method to be alerted when cleanup needs to be done or poll the queue.

"Java theory and practice: Plugging memory leaks with weak references" explains:

The implementation of WeakHashMap illustrates a common idiom with weak references -- that some internal object extends WeakReference.

...

WeakHashMap uses weak references for holding map keys, which allows the key objects to be garbage collected when they are no longer used by the application, and the get() implementation can tell a live mapping from a dead one by whether WeakReference.get() returns null. But this is only half of what is needed to keep a Map's memory consumption from increasing throughout the lifetime of the application; something must also be done to prune the dead entries from the Map after the key object has been collected. Otherwise, the Map would simply fill up with entries corresponding to dead keys. And while this would be invisible to the application, it could still cause the application to run out of memory because the Map.Entry and value objects would not be collected, even if the key is.

...

Reference queues are the garbage collector's primary means of feeding back information to the application about object lifecycle. Weak references have two constructors: one takes only the referent as an argument and the other also takes a reference queue. When a weak reference has been created with an associated reference queue and the referent becomes a candidate for GC, the reference object (not the referent) is enqueued on the reference queue after the reference is cleared. The application can then retrieve the reference from the reference queue and learn that the referent has been collected so it can perform associated cleanup activities, such as expunging the entries for objects that have fallen out of a weak collection. (Reference queues offer the same dequeuing modes as BlockingQueue -- polled, timed blocking, and untimed blocking.)

EDIT:

Even with queues, weak maps can still leak. Ephemerons are an attempt to solve the case where a weak key references a strongly held value that references the key. They are not implementable in java.

Ephemerons solve a problem which is commonly found when trying to "attach" properties to objects by using a registry. When some property should be attached to an object, the property should (in terms of GC behavior) typically have the life-time that an instance variable of this object would have. However, this is complicated by having an external association between the object and its property such as:

property --------- registry --------- association --------- object

Here, the registry (a third party) will hold onto the association itself which would require manual removal from the registry (instead of automated garbage collection). While this problem can always be solved in any given concrete situation by using one of the various weak association types, choosing the 'right' kind of association depends on a variety of factors some of which can change dynamically.

Ephemerons solve this problem by defining that the 'contents' (value) of an ephemeron will be held strongly until the key is known to be garbage collected. From then on, the contents of the ephemeron will be held weakly. Therefore, the contents of an ephemeron can become eligible for garbage collection if and only if the key is garbage collectable which is the exact behavior which we would observe for an instance variable of the object.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文