高 基础
引用类型(强软弱虚)#
一句话答案#
四种引用强度递减:强引用不回收、软引用内存不足时回收、弱引用 GC 就回收、虚引用仅跟踪回收时机。
核心要点
| 引用类型 | 回收时机 | 用途 |
|---|---|---|
强引用 Object o = new Object() | 永不回收(只要可达) | 普通变量 |
软引用 SoftReference | 内存不足时回收 | 缓存(如图片缓存) |
弱引用 WeakReference | 下次 GC 就回收 | ThreadLocalMap 的 key |
虚引用 PhantomReference | 随时可回收 | 跟踪对象被回收的时机(堆外内存管理) |
ThreadLocal 与弱引用:
- ThreadLocalMap 的 key 是 WeakReference
- ThreadLocal 对象被 GC 后,key 变 null,但 value 还在 → 内存泄漏
- 解决:用完必须
remove()
软引用实际应用:
SoftReference<byte[]> cache = new SoftReference<>(new byte[1024*1024]);
byte[] data = cache.get(); // 内存够就返回,不够被回收返回nulljava面试回答(2分钟版)
Java 中有四种引用类型,强度依次递减。强引用就是我们平时用的普通引用,只要引用存在对象就不会被 GC 回收。软引用 SoftReference 在内存充足时不会被回收,只有当 JVM 即将 OOM 时才回收,适合做内存敏感的缓存,比如图片缓存。弱引用 WeakReference 不管内存够不够,下次 GC 时一定会被回收,最典型的应用是 ThreadLocalMap 的 key,Entry 继承了 WeakReference,当 ThreadLocal 对象没有外部强引用时 key 会被 GC 回收变成 null,但 value 仍然是强引用不会自动清理,这就是 ThreadLocal 内存泄漏的根源,所以用完 ThreadLocal 必须调用 remove。虚引用 PhantomReference 最弱,get 方法永远返回 null,唯一用途是通过引用队列跟踪对象被 GC 回收的时机,常用于堆外内存的清理,比如 DirectByteBuffer 的回收。理解四种引用对于排查内存泄漏和设计缓存策略非常重要。
追问与易错
追问方向:
- “ThreadLocal 的 key 为什么用弱引用?”→ 如果用强引用,即使 ThreadLocal 对象不再使用,Entry 仍然强引用它导致无法 GC;弱引用让 ThreadLocal 对象失去外部引用后可被回收,但 value 仍需手动 remove 清理
- “软引用什么时候用?”→ 适合做内存敏感的缓存,如图片缓存、页面缓存;内存充足时保留提升性能,内存不足时自动回收避免 OOM,比手动管理缓存淘汰更简单
- “虚引用的实际用途?”→ 通过 ReferenceQueue 跟踪对象被 GC 回收的时机,用于堆外内存清理(如 DirectByteBuffer 通过 Cleaner + PhantomReference 回收直接内存)
易错点:
- ❌ 弱引用马上就被回收——是下次 GC 时回收
- ❌ 混淆引用类型和 GC Roots