在 Java 中,WeakReference
(弱引用)和 SoftReference
(软引用)都是用于优化内存管理的特殊引用类型,它们与强引用的核心区别在于垃圾收集器(GC)回收其指向对象的时机不同。主要区别如下:
1. 回收时机
- WeakReference (弱引用):当对象仅被弱引用指向且没有强引用时,无论当下内存是否充足,垃圾收集器都会在下一个 GC 周期中立即回收该对象。
- SoftReference (软引用):当对象仅被软引用指向且没有强引用时,仅在 JVM 内存不足(即将抛出
OutOfMemoryError
前)时,垃圾收集器才会回收该对象。软引用对象在内存充足时可长期保留。
2. 适用场景
- WeakReference 适用场景:
- 需严格避免内存泄漏但对象可快速重建的场景(如
WeakHashMap
的键、临时性缓存、监听器列表)。 - 对象生命期短暂且回收延迟不可接受的场景。
- 需严格避免内存泄漏但对象可快速重建的场景(如
- SoftReference 适用场景:
- 需缓存非必需但重建成本较高的对象(如图片缓存、计算结果缓存),允许在内存紧张时释放资源。
- 优先保留对象至内存不足时再回收的场景。
3. 与引用队列(ReferenceQueue
)关联
- 两者均可关联
ReferenceQueue
:当被引用对象被 GC 回收后,对应的WeakReference
或SoftReference
对象会被加入队列,便于清理无效引用。 - 典型应用:实现缓存自动清理机制。
4. 示例对比
// WeakReference 示例
WeakReference<byte[]> weakRef = new WeakReference<>(new byte[1024]);
System.gc(); // GC 后 weakRef.get() 大概率返回 null
// SoftReference 示例
SoftReference<byte[]> softRef = new SoftReference<>(new byte[1024 * 1024]);
System.gc(); // 内存充足时 softRef.get() 仍有效
// 当内存不足时,GC 会自动回收 softRef 指向的对象
核心区别总结
特性 | WeakReference (弱引用) | SoftReference (软引用) |
---|---|---|
回收条件 | 无强引用即回收(下次 GC 必然回收) | 无强引用且内存不足时回收(延迟回收) |
内存敏感度 | 低(忽略内存状态) | 高(依赖内存压力) |
典型用途 | 防内存泄漏的临时缓存、监听器 | 可牺牲的大对象缓存(如图片、数据) |
通俗而言:弱引用对象“见死不救”,一旦失去强引用支持立刻被回收;软引用对象“尽力维持”,直到内存告急才被迫放弃。