主题切换
四种引用(强、软、弱、虚)
一、强引用
1. 定义与回收规则
普通对象赋值即为强引用,只要GC Roots存在强引用链指向该对象,永远不会被回收;只有切断所有强引用,对象才会判定为垃圾。
java
User user = new User();2. 特点与场景
日常代码默认使用,容易造成内存泄漏(静态集合持有对象长期不释放)。
二、软引用 SoftReference
1. 回收规则
仅存在软引用指向对象时:
- 普通GC不会回收;
- 堆内存不足、即将发生OOM时,会主动回收所有软引用对象释放内存。
java
User user = new User();
SoftReference<User> softRef = new SoftReference<>(user);
user = null;2. 使用场景
缓存框架,内存充足时缓存复用,内存紧张自动清理缓存。
三、弱引用 WeakReference
1. 回收规则
仅存在弱引用指向对象时,只要发生GC,无论内存是否充足,都会直接回收。
java
User user = new User();
WeakReference<User> weakRef = new WeakReference<>(user);
user = null;2. 延伸:ThreadLocal内存泄漏
ThreadLocal底层Entry继承WeakReference<ThreadLocal<?>>:
- key是弱引用,线程GC时ThreadLocal实例会被回收;
- value是强引用,若线程长期存活(线程池),value无法释放,造成内存泄漏; 解决:使用完调用
remove()清除value。
四、虚引用 PhantomReference
1. 基础规则
- 必须搭配
ReferenceQueue引用队列使用; - 无法通过
get()获取原对象,仅用于跟踪对象回收时机; - 对象被回收后,虚引用实例会被放入队列,由
Reference Handler后台线程处理资源释放。
java
User user = new User();
ReferenceQueue<Object> queue = new ReferenceQueue<>();
PhantomReference<User> phantomRef = new PhantomReference<>(user, queue);
user = null;2. 使用场景
管理堆外直接内存,对象回收时通过队列回调释放Native内存,避免堆外内存泄漏。
五、四种引用总结
- 强引用:GC Roots可达则永不回收,常规对象使用;
- 软引用:内存充足保留,内存不足OOM前回收,做缓存;
- 弱引用:只要GC就回收,ThreadLocal、临时缓存;
- 虚引用:仅跟踪回收时机,配合队列释放堆外资源。
六、面试简答
问:强引用、软引用、弱引用、虚引用的区别?
答:
- 强引用:普通赋值引用,只要GC Roots可达,不会被回收;
- 软引用SoftReference:内存充足时存活,堆内存不够即将OOM时回收,适合缓存;
- 弱引用WeakReference:每次GC都会回收,ThreadLocal底层使用弱引用key,不手动remove会出现value内存泄漏;
- 虚引用PhantomReference:必须绑定引用队列,无法获取对象,仅在对象回收后入队,用来释放堆外直接内存。