WeakHashMap的键为弱引用,GC时无强引用即可能被清理,值仍强引用;键回收不实时,依赖GC时机,且受外部强引用影响;需防常量池键、线程安全及循环引用导致的内存泄漏。

WeakHashMap 的键是弱引用,垃圾回收时只要没有强引用指向该键,它就可能被清理,进而整个键值对从表中移除。
键被回收的时机取决于 GC 而非使用频率
WeakHashMap 不会主动清理“过期”键;它依赖 JVM 的垃圾回收器识别并清除无强引用的键。这意味着:
- 即使键已不可达,也不一定立刻消失——要等下一次 GC(尤其是老年代 GC)实际运行后才可能被移除
- 如果键对象被其他地方(如静态集合、线程局部变量、缓存等)持有强引用,它就不会被回收,对应条目也一直保留在 WeakHashMap 中
- 调用
size()或遍历前,WeakHashMap 会隐式清理部分已回收的条目,但不保证完全清理
值对象的生命周期不受 WeakHashMap 约束
WeakHashMap 只对键使用弱引用,值对象仍通过强引用持有。因此:
- 即使键被回收,只要值对象被外部强引用着,它就不会被 GC
- 若值对象又持有了键的引用(比如内部类、闭包等),会造成循环引用,导致键无法被回收,引发内存泄漏
- 必要时应手动将值设为 null 或使用弱/软引用来管理值,避免意外驻留
实际使用中的典型风险
WeakHashMap 常用于缓存、监听器注册、元数据绑定等场景,但容易踩坑:
- 用字符串字面量或 Integer 等常量池对象作键:它们被 JVM 强引用,永远不会被回收,WeakHashMap 失去意义
- 在多线程环境下未同步访问:WeakHashMap 本身不保证线程安全,GC 清理与遍历可能并发冲突,建议外层加锁或改用
ConcurrentHashMap+ 显式清理逻辑 - 误以为“自动清理 = 实时清理”:在延迟敏感或内存紧张场景,需配合
expungeStaleEntries()主动触发清理(该方法是 protected,可通过反射或继承调用)
不复杂但容易忽略:WeakHashMap 是工具,不是银弹;它解决的是“避免因缓存持有键而导致内存泄漏”的问题,而不是替代合理生命周期管理。
















