在java中,对象的引用强度被分为四种,从强到弱一次是:强引用 → 软引用 → 弱引用 → 虚引用
它们都位于 java.lang.ref 包中,主要用于内存管理、缓存设计、避免 OOM 等场景
一、强引用(Strong Reference)
1、定义:最常见、默认的引用方式,只要强引用还存在,GC永远不会回收该对象。
Object obj = new Object(); obj 就是一个强引用。
2、GC 行为:不会回收,即使内存不足,也不会回收。内存不足时直接抛
OutOfMemoryError
3、示例:
Object obj = new Object();
obj = null; // 断开强引用
只有当obj = null后,对象才有资格被GC回收。
4、使用场景:业务核心对象,普通成员变量、局部变量,生命周期明确,不能被回收的对象。
二、软引用(Soft Reference)
1、定义:内存不足时才会被GC 回收,适合做缓存
SoftReference softRef = new SoftReference<>(new Object());
2、GC 行为: 内存充足->不回收。内存不足->优先回收软引用对象,比OOM更早回收。
3、示例:
SoftReference<byte[]> ref = new SoftReference<>(new byte[10 * 1024 * 1024]);
byte[] data = ref.get(); // 可能为 null
使用前必须判空
4、使用场景:缓存系统(图片缓存、本地数据缓存)类似 LRU + JVM GC 的缓存策略
三、弱引用(Weak Reference)
1、定义:只要发生GC,就会被回收,不管内存是否充足
WeakReference weakRef = new WeakReference<>(new Object());
2、GC行为:只要发生GC->立刻回收,回收率非常高。
3、示例:
WeakReference weakRef = new WeakReference<>(new Object());
System.gc();
Object obj = weakRef.get(); // 大概率为 null
4、使用场景:
① WeakHashMap
Map<Object, String> map = new WeakHashMap<>();
key 是弱引用
key 没有强引用时,Entry 自动删除
② 防止内存泄漏
ThreadLocal
监听器(Listener)
回调对象 📌 ThreadLocal 内部就是弱引用 key
四、虚引用(Phantom Reference)
1、定义
最弱的一种引用
get() 永远返回 null
必须和 ReferenceQueue 配合使用
PhantomReference phantomRef =
new PhantomReference<>(new Object(), referenceQueue);
2、GC行为
对象被回收前 → 放入 ReferenceQueue
无法通过虚引用获取对象
3、示例:
ReferenceQueue queue = new ReferenceQueue<>();
PhantomReference ref =
new PhantomReference<>(new Object(), queue);
// 监控对象被回收
Reference<?> r = queue.poll();
4、使用场景
对象回收前通知
资源释放(直接内存、堆外内存)
NIO / Netty
Cleaner、Unsafe 底层机制
五、四种引用对比总结
| 引用类型 | GC 时是否回收 | get() | 典型用途 |
|---|---|---|---|
| 强引用 | ❌ 永不回收 | 有值 | 普通对象 |
| 软引用 | 内存不足才回收 | 可能为 null | 缓存 |
| 弱引用 | GC 就回收 | 大概率 null | 防泄漏 |
| 虚引用 | 回收前通知 | 永远 null | 资源释放 |