Javadocs 说“当一个键被丢弃时,它的条目就被有效地从映射中删除了”。
但是除非有另一个线程偶尔会删除这些Map.Entry
条目,否则值对象不会被映射强引用吗?但是由于没有这样的线程在运行,只有get
方法调用可以删除这样的条目——一次一个。
我几乎总是WeakHashMap<K, WeakReference<V>>
因为这个原因使用。为什么他们不将其设为默认行为 - 值也作为弱引用?
Javadocs 说“当一个键被丢弃时,它的条目就被有效地从映射中删除了”。
但是除非有另一个线程偶尔会删除这些Map.Entry
条目,否则值对象不会被映射强引用吗?但是由于没有这样的线程在运行,只有get
方法调用可以删除这样的条目——一次一个。
我几乎总是WeakHashMap<K, WeakReference<V>>
因为这个原因使用。为什么他们不将其设为默认行为 - 值也作为弱引用?
引用队列用于自动删除条目。
http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/ref/ReferenceQueue.html
参考队列,在检测到适当的可达性更改后,垃圾收集器会将已注册的参考对象附加到这些队列中。
基本上,弱引用是垃圾收集器的核心部分,因此当发生 GC 扫描时,会找到未使用的引用并将其放入队列中,然后可以根据这些队列的内容采取行动。
线程可以坐在队列的remove
方法上,以便在需要清理或poll
队列时收到警报。
的实现
WeakHashMap
说明了一个带有弱引用的常见习语——一些内部对象扩展WeakReference
。...
WeakHashMap
使用弱引用来保存映射键,这允许在应用程序不再使用键对象时对其进行垃圾回收,并且get()
实现可以通过是否WeakReference.get()
返回来区分活动映射和死映射null
。但这只是在应用程序的整个生命周期中保持 Map 的内存消耗不增加所需的一半;在收集到关键对象后,还必须做一些事情来从 Map 中删除死条目。否则,Map 将简单地填充与死键对应的条目。虽然这对应用程序是不可见的,但它仍然可能导致应用程序耗尽内存,因为不会收集 Map.Entry 和 value 对象,即使键是。...
引用队列是垃圾收集器向应用程序反馈有关对象生命周期的信息的主要方式。弱引用有两个构造函数:一个只接受所指对象作为参数,另一个也接受一个引用队列。当弱引用与关联的引用队列一起创建并且引用对象成为 GC 的候选对象时,引用对象(而不是引用对象)会在引用被清除后排入引用队列。然后,应用程序可以从引用队列中检索引用并获悉该引用已被收集,因此它可以执行相关的清理活动,例如清除已从弱集合中删除的对象的条目。(参考队列提供与 BlockingQueue 相同的出队模式——轮询、定时阻塞和不定时阻塞。)
编辑:
即使有队列,weak map 仍然会泄漏。 Ephemerons试图解决弱键引用引用该键的强保持值的情况。它们在 java 中是不可实现的。
Ephemerons 解决了在尝试使用注册表将属性“附加”到对象时常见的问题。当某个属性应该附加到一个对象时,该属性应该(就 GC 行为而言)通常具有该对象的实例变量所具有的生命周期。但是,由于对象与其属性之间存在外部关联,这会变得复杂,例如:
property --------- registry --------- association --------- object
在这里,注册表(第三方)将保留关联本身,这需要从注册表中手动删除(而不是自动垃圾收集)。虽然这个问题总是可以在任何给定的具体情况下通过使用各种弱关联类型之一来解决,但选择“正确”的关联类型取决于多种因素,其中一些因素可以动态变化。
蜉蝣通过定义蜉蝣的“内容”(值)将被强保持直到已知密钥被垃圾收集来解决这个问题。从那时起,蜉蝣的内容将被弱持有。因此,当且仅当键是可垃圾回收的,即我们将观察到的对象实例变量的确切行为时,ephemeron 的内容才有资格进行垃圾回收。