WeakHashMap通过弱引用键+引用队列+懒清理机制实现键的自动回收:键被包装为WeakReference子类Entry,GC后通过expungeStaleEntries()扫描队列清理失效Entry;值仍为强引用,需手动置null防泄漏。

WeakHashMap 通过将键包装为 WeakReference,并依赖 JVM 的垃圾回收机制,在 GC 发现键无强引用时自动清理对应 Entry,从而实现弱引用键的自动回收。
键被包装成 WeakReference 存储
WeakHashMap 内部不直接持有键的强引用,而是把每个键封装进一个自定义的 WeakReference 子类 —— Entry(它继承自 WeakReference)。这意味着只要外部没有其他强引用指向该键对象,它就可能在下一次 GC 中被回收。
- Entry 构造时传入键和引用队列(
ReferenceQueue),用于后续追踪被回收的键 - 值(value)仍以强引用方式保存,不会因键回收而自动清除
- 注意:WeakHashMap 的“弱”仅作用于键,值仍是强引用,需手动置 null 避免内存泄漏
GC 后通过引用队列清理失效 Entry
WeakHashMap 并不主动轮询或实时检测键是否存活。它采用“懒清理”策略:每次调用 get、put、size 等方法前,先调用私有方法 expungeStaleEntries() 扫描内部的引用队列,把已被 GC 回收键所对应的 Entry 从哈希表中移除。
- 引用队列在键被回收时自动入队该 Entry 实例
- 清理过程是单向链表遍历 + 表项删除,开销较小,但不是实时的
- 若长时间不调用任何 public 方法,失效 Entry 可能暂时滞留(但不会影响正确性)
典型使用场景与注意事项
WeakHashMap 常用于缓存、监听器注册、元数据映射等需要“自动解绑”的场景,避免因忘记移除导致内存泄漏。
- 适合键是临时对象(如 GUI 组件、线程局部对象),生命周期不由 Map 控制
- 不要用 String、Integer 等常量池对象作键 —— 它们可能被强引用持有,无法及时回收
- 遍历时应使用
entrySet().iterator()并配合hasNext(),避免因并发修改抛出异常;也可用增强 for 循环(底层仍走迭代器) - 若需弱引用值,需自行组合
WeakReference,WeakHashMap 不提供该能力
不复杂但容易忽略的是:它的自动回收不是魔法,而是弱引用语义 + 引用队列 + 懒清理三者协作的结果。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











