强引用缓存使对象长期驻留内存,需手动释放;弱引用缓存则在每次GC时立即回收,适合临时非关键数据,但不可控的存活时间导致缓存失效频繁,通用缓存应优先考虑软引用。

强引用和弱引用在本地缓存中表现截然不同:强引用会让缓存对象长期驻留内存,哪怕已无业务使用;弱引用则让对象“朝生暮死”,只要触发 GC 就可能被立即回收,不考虑内存是否紧张。
强引用缓存:不释放,直到你手动切断
用普通变量或 HashMap 直接持有对象(如 cache.put(key, new Data())),就是强引用缓存。JVM 会把它当“刚需”对待——哪怕堆快爆了,也宁可抛 OutOfMemoryError,也不会动它。
- 适合极少数必须全程保活、生命周期与应用一致的对象(比如全局配置单例)
- 但用于一般缓存极易引发内存泄漏:例如静态 Map 不断 put,又忘了 remove,对象就再也收不回来
- 想释放?只能显式调用
clear()、remove(),或把引用赋值为null,再等下次 GC
弱引用缓存:GC 一扫就清,不讲情面
用 WeakReference<Data> 包一层再存入缓存结构(如 WeakHashMap 或自定义容器),对象就只靠弱引用维系。一旦 GC 线程运行,不管堆还剩多少空间,只要扫描到它,立刻回收。
- 适合临时性、非关键的映射关系,比如 UI 组件绑定的数据快照、短期解析中间结果
-
WeakHashMap是典型用法:key 是弱引用,key 对象一被回收,对应 entry 自动失效,避免内存堆积 - 注意:value 仍可能是强引用,若 value 又反向引用 key,就可能阻止 key 回收,造成“伪泄漏”
为什么不用弱引用做通用缓存?
因为它的存活时间不可控。用户刚查完数据,GC 恰好跑一轮,缓存就空了,下次还得重算——缓存命中率趋近于零,失去缓存意义。
- 弱引用不是“懒回收”,而是“激进回收”:不等内存告急,只等 GC 到来
- 它适合的是“有更好,没有也行”的场景,而非“尽量留着,实在不行再丢”
- 真要做内存敏感缓存,软引用(
SoftReference)才是更合理的选择:它会在 OOM 前才批量清理,平衡了保留与释放
一个简单对比示例
假设缓存一张图片对象:
- 强引用方式:
Map<String, BufferedImage> cache = new HashMap<>(); cache.put("logo", img);→img会一直占内存,除非你主动remove - 弱引用方式:
Map<String, WeakReference<BufferedImage>> cache = new HashMap<>(); cache.put("logo", new WeakReference<>(img));→ 下次 GC 后,cache.get("logo").get()很可能返回null

















