引用队列用于自动删除条目。
http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/ref/ReferenceQueue.html http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/ref/ReferenceQueue.html
引用队列,在检测到适当的可达性更改后,垃圾收集器将已注册的引用对象附加到该队列。
基本上,弱引用是垃圾收集器的核心部分,因此当发生 GC 扫描时,会找到未使用的引用并将其放入队列中,然后可以根据这些队列的内容采取操作。
一个线程可以坐在队列中remove http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/ref/ReferenceQueue.html#remove()需要进行清理时发出警报的方法或poll
队列。
《Java 理论与实践:用弱引用堵住内存泄漏》 http://www.ibm.com/developerworks/java/library/j-jtp11225/解释:
实施WeakHashMap
说明了弱引用的常见用法——某些内部对象扩展WeakReference
.
...
WeakHashMap
使用弱引用来保存映射键,这允许键对象在应用程序不再使用时被垃圾收集,并且get()
实现可以通过是否区分活动映射和死映射WeakReference.get()
回报null
。但这只是在应用程序的整个生命周期中防止 Map 内存消耗增加所需的一半;在收集关键对象后,还必须采取一些措施从 Map 中删除死条目。否则,映射将简单地填充与死键对应的条目。虽然这对应用程序来说是不可见的,但它仍然可能导致应用程序内存不足,因为即使键被收集,Map.Entry 和值对象也不会被收集。
...
引用队列是垃圾收集器向应用程序反馈有关对象生命周期的信息的主要方式。弱引用有两个构造函数:一个仅将引用对象作为参数,另一个也采用引用队列。当创建了具有关联引用队列的弱引用并且引用对象成为 GC 的候选者时,引用对象(而不是引用对象)在引用被清除后将排队到引用队列中。然后,应用程序可以从引用队列中检索引用,并获悉引用对象已被收集,以便它可以执行关联的清理活动,例如删除已从弱集合中删除的对象的条目。 (引用队列提供与 BlockingQueue 相同的出队模式——轮询、定时阻塞和不定时阻塞。)
EDIT:
即使有队列,弱映射仍然可能泄漏。蜉蝣 http://en.wikipedia.org/wiki/Ephemeron是尝试解决弱密钥引用引用该密钥的强保留值的情况。它们无法在 java 中实现。
蜉蝣解决了尝试使用注册表将属性“附加”到对象时常见的问题。当某个属性应该附加到一个对象时,该属性(就 GC 行为而言)通常应该具有该对象的实例变量所具有的生命周期。然而,由于对象及其属性之间存在外部关联,这会变得复杂,例如:
property --------- registry --------- association --------- object
在这里,注册表(第三方)将保留关联本身,这需要从注册表中手动删除(而不是自动垃圾收集)。虽然这个问题总是可以在任何给定的具体情况下通过使用各种弱关联类型之一来解决,但选择“正确”的关联类型取决于多种因素,其中一些因素可以动态变化。
星历通过定义星历的“内容”(值)将被严格保留,直到已知密钥被垃圾收集为止,从而解决了这个问题。从此以后,星历的内容将被弱化。因此,当且仅当键是可垃圾收集的时,星历的内容才可以进行垃圾收集,这正是我们在对象的实例变量中观察到的行为。