Java引用类型

Java 引用类型

ℹ️ 信息: 衍生来源
本笔记衍生自 ThreadLocal原理-弱引用设计

概述

Java 从 JDK 1.2 开始提供了四种引用类型,用于更灵活地控制对象的生命周期和垃圾回收行为。

四种引用类型

引用类型 GC 回收时机 是否可获取对象
强引用 直接引用 永不回收(除非不可达)
软引用 SoftReference 内存不足时回收 是(未回收前)
弱引用 WeakReference 下次 GC 时回收 是(未回收前)
虚引用 PhantomReference 随时可能回收

^ref-types

graph TD
    A[引用强度] --> B[强引用 Strong]
    B --> C[软引用 Soft]
    C --> D[弱引用 Weak]
    D --> E[虚引用 Phantom]
    
    style B fill:#ff6b6b
    style C fill:#feca57
    style D fill:#48dbfb
    style E fill:#c8d6e5

详细说明

1. 强引用(Strong Reference)

最常见的引用类型,只要强引用存在,对象就不会被 GC 回收。

1
2
Object obj = new Object();  // 强引用
obj = null; // 断开引用后才可能被回收

特点

  • 默认的引用类型
  • 即使 OOM 也不会回收强引用对象
  • 需要手动置 null 才能让 GC 回收

2. 软引用(Soft Reference)

内存充足时不会回收,内存不足时会被回收。

1
2
3
4
5
6
7
SoftReference<byte[]> softRef = new SoftReference<>(new byte[1024 * 1024]);

byte[] data = softRef.get(); // 获取对象,可能为 null
if (data == null) {
// 对象已被回收,需要重新创建
data = new byte[1024 * 1024];
}

应用场景

场景 说明
缓存 图片缓存、网页缓存
内存敏感数据 可重建的大对象

3. 弱引用(Weak Reference)

只要发生 GC,无论内存是否充足,都会被回收。

1
2
3
4
5
6
WeakReference<Object> weakRef = new WeakReference<>(new Object());

Object obj = weakRef.get(); // 可能返回 null
if (obj == null) {
// 对象已被 GC 回收
}

弱引用解决的问题

⚠️ 重要: 核心价值
弱引用允许对象在没有其他强引用时被 GC 回收,避免内存泄漏

以 ThreadLocal 为例:

1
2
3
4
5
ThreadLocalMap.Entry 的 key 使用弱引用

场景:ThreadLocal 变量不再使用
├── 如果 key 是强引用 → ThreadLocal 对象无法回收 → 内存泄漏
└── 如果 key 是弱引用 → ThreadLocal 对象可被 GC 回收 → 避免泄漏

应用场景

场景 示例
ThreadLocalMap Entry 的 key 使用弱引用
WeakHashMap key 被回收后自动移除 entry
监听器/回调 避免因注册监听器导致对象无法回收

4. 虚引用(Phantom Reference)

最弱的引用,无法通过虚引用获取对象,主要用于跟踪对象被回收的状态。

1
2
3
4
5
6
7
8
9
10
11
ReferenceQueue<Object> queue = new ReferenceQueue<>();
PhantomReference<Object> phantomRef = new PhantomReference<>(new Object(), queue);

// get() 永远返回 null
Object obj = phantomRef.get(); // null

// 对象被回收后,虚引用会被放入队列
Reference<?> ref = queue.poll();
if (ref != null) {
// 对象已被回收,执行清理操作
}

应用场景

场景 说明
资源清理 替代 finalize() 进行资源释放
堆外内存管理 DirectByteBuffer 的 Cleaner 机制
对象回收监控 跟踪对象何时被 GC 回收

引用队列(ReferenceQueue)

软引用、弱引用、虚引用都可以关联引用队列,当对象被回收时,引用对象会被放入队列。

1
2
3
4
5
6
7
8
9
ReferenceQueue<Object> queue = new ReferenceQueue<>();
WeakReference<Object> weakRef = new WeakReference<>(new Object(), queue);

// GC 后检查队列
System.gc();
Reference<?> ref = queue.poll();
if (ref == weakRef) {
// 弱引用指向的对象已被回收
}

对比总结

特性 强引用 软引用 弱引用 虚引用
回收时机 不可达时 内存不足时 GC 时 随时
get() 返回 对象 对象/null 对象/null null
典型用途 普通对象 缓存 避免内存泄漏 回收跟踪
是否需要队列 - 可选 可选 必须

相关链接

  • Java/并发编程/基础知识/ThreadLocal原理 - 衍生来源,弱引用的典型应用

Java引用类型
https://zmmmmy.github.io/2026/01/10/Java引用类型/
作者
ZhiMy
发布于
2026年1月10日
许可协议