weakreference 的核心作用是“不阻止回收”,用于切断隐式强引用链防泄漏,而非延缓回收或充当缓存;适用于监听器、weakhashmap、threadlocal 场景,需配合判空、remove 和合理设计。

WeakReference 的作用不是“让对象晚点被回收”,而是“不阻止回收”——只要对象没其他强引用,GC 一来就清。它解决的是不该持有却意外持有了的问题,核心是切断隐式强引用链。
用 WeakReference 打破监听器/回调导致的泄漏
UI 组件(如 Activity、Fragment、View)注册监听器后,若监听器是匿名或非静态内部类,会隐式持有外部类强引用。当组件已销毁,但监听器仍被框架(如 Handler、EventBus、线程池)长期持有,就会泄漏。
改法:把外部类引用包装成 WeakReference,在使用前判空:
- 定义一个静态的 OnClickListener 子类,构造时接收 WeakReference
- onClick 中先调用 activityRef.get(),为 null 就直接 return
- 避免在 get() 返回 null 后还调用 startActivity() 或 findViewById()
用 WeakHashMap 替代静态 Map 缓存短生命周期 key
静态集合(如 static Map
WeakHashMap 能自动解耦:它的 key 是弱引用。一旦 Activity 离开前台且无其他强引用,下次 GC 后对应 Entry 就从 Map 中消失。
- 适用于以 View、Activity、Context 为 key 的映射场景
- 不适用于 value 也需要随 key 一起释放的场景;此时需手动封装 value 为 WeakReference
- WeakHashMap 不保证实时清理,Entry 消失发生在 GC 后,不是立即发生
配合 ThreadLocal 使用时主动清理
ThreadLocal 自身的 key 已是 WeakReference,但 value 是强引用。在线程池中,线程复用导致 value 长期滞留,而 ThreadLocal 实例可能早已不可达(key 变 null),形成“幽灵 entry”。
- 每次用完必须显式调用 threadLocal.remove(),推荐放在 finally 块或 try-with-resources 中
- 若 value 是大对象(如缓存数据、连接句柄),可将其再包一层 WeakReference,降低滞留风险
- 不要依赖 ThreadLocal 的 key 弱引用自动解决问题——value 的强引用才是泄漏主因
避免把 WeakReference 当缓存用
WeakReference 不适合做通用缓存:它没有淘汰策略、不可控、GC 一触发就丢,命中率极低。LruCache、Caffeine 等才是缓存正解。
- WeakReference 的合理定位是“防泄漏的辅助工具”,不是“缓存容器”
- 若真要弱化 value 引用,优先考虑 SoftReference + 主动大小控制 + null 清理逻辑
- 反复 new WeakReference 包装同一对象,反而增加 GC 压力,应复用或按需创建
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











