WeakHashMap 的 Entry 继承 WeakReference,key 仅弱可达,无外部强引用时可能被 GC 回收;回收后需通过 ReferenceQueue 和 expungeStaleEntries() 主动清理;value 为强引用,若反向引用 key 会导致内存泄漏;清理依赖访问触发,无后台机制,延迟不可控。

WeakHashMap 的 Entry 继承 WeakReference,本质是让 key 失去“阻止 GC”的能力——只要外部没有强引用指向该 key,它就可能在下一次垃圾回收中被清除。
Entry 是 WeakReference 的子类,key 就是 referent
WeakHashMap 内部的 Entry 类直接继承自 WeakReference<K>,构造时把传入的 key 作为弱引用的 referent:
- 这意味着 JVM 从 GC Roots 出发做可达性分析时,不会因这个 Entry 而将 key 视为“强可达”
- key 是否存活,完全取决于外部是否存在至少一个强引用(比如局部变量、静态字段、其他对象的成员变量等)
- 一旦所有强引用消失,key 就变成“仅弱可达”,GC 线程在下次执行(尤其是老年代或 Full GC)时大概率将其回收
回收不是即时的,依赖 ReferenceQueue + 主动清理
key 被 GC 回收后,并不会立刻从 WeakHashMap 中消失。实际清理靠两步配合:
- JVM 自动将已回收 key 对应的 WeakReference(即那个 Entry)加入内部绑定的 ReferenceQueue
- WeakHashMap 在多数公开方法(如 get()、put()、size()、keySet())开头隐式调用 expungeStaleEntries()
- 该方法遍历 ReferenceQueue,逐个取出已入队的 Entry,并从哈希表中真正删除对应桶链中的节点
value 不受弱引用保护,容易引发内存泄漏
WeakHashMap 只对 key 做弱引用,value 始终是强引用:
立即学习“Java免费学习笔记(深入)”;
- key 被回收后,如果 value 没有被其他地方引用,它会随 Entry 清理而自然释放
- 但若 value 反向持有 key(例如:value 是监听器,内部捕获了 key;或 value 是 Handler/Runnable,隐式引用了外部类实例,而该实例又持有了 key),就会形成强引用闭环
- 此时 key 永远无法被 GC,WeakHashMap 形同虚设,条目长期滞留,造成内存泄漏
不访问就不会清理,延迟不可控
WeakHashMap 不启动后台线程、不轮询、不设超时:
- 如果创建后一直没调用任何 public 方法,即使 key 已被 GC,Entry 仍会卡在哈希表里,占用空间
- 清理时机完全由 GC 触发时间和业务访问频率决定,无法预测
- 所以它适合“高频读写+天然有外部强引用生命周期”的场景(如缓存 UI 控件与配置映射),不适合需要精确控制存活时间的用途


















