当前位置: 首页 > news >正文

Java中的四大引用类型详解

Java中的四大引用类型详解:强引用、软引用、弱引用、虚引用

1. 引用类型概览

Java提供了四种不同强度的引用类型,用于控制对象的生命周期和垃圾回收行为:

引用类型回收时机典型应用场景是否影响GC
强引用永不回收(除非断开引用)普通对象创建不回收
软引用内存不足时回收缓存实现可能回收
弱引用下次GC必定回收临时缓存/监听器必定回收
虚引用随时可能回收(跟踪回收状态)对象回收跟踪特殊用途

2. 强引用(Strong Reference)

特点

  • 默认引用类型Object obj = new Object()就是强引用
  • 回收条件:只有当没有任何强引用指向对象时才会被回收

代码示例

// 强引用示例
String strongRef = new String("Strong Reference");

// 断开强引用(此时对象可被GC回收)
strongRef = null; 

内存泄漏场景

List<Object> leakList = new ArrayList<>();
while(true) {
    leakList.add(new Object()); // 不断添加对象且不释放
}
// 即使不再使用,由于List持有强引用,对象无法被回收

3. 软引用(Soft Reference)

特点

  • 内存敏感缓存:当内存不足时才会被回收
  • 比弱引用"强":JVM会尽量保留软引用对象

代码示例

// 创建软引用
SoftReference<byte[]> softRef = 
    new SoftReference<>(new byte[1024 * 1024]); // 1MB

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

典型应用

  • 图片缓存(Android的LruCache内部使用)
  • 计算结果缓存(当内存紧张时自动释放)

4. 弱引用(Weak Reference)

特点

  • 短期缓存:只要发生GC就会被回收
  • 不会阻止回收:比软引用更脆弱

代码示例

// 创建弱引用
WeakReference<Object> weakRef = 
    new WeakReference<>(new Object());

// 手动触发GC(仅用于演示)
System.gc();

// 大概率返回null
System.out.println(weakRef.get()); 

典型应用

// 1. WeakHashMap键的自动清理
WeakHashMap<Object, String> map = new WeakHashMap<>();
map.put(new Object(), "value"); // 键对象无其他强引用时会被自动移除

// 2. 监听器防内存泄漏
public class MyListener {
    void register() {
        someService.register(new WeakReference<>(this));
    }
}

5. 虚引用(Phantom Reference)

特点

  • 最弱引用:无法通过get()获取对象
  • 回收跟踪:用于监控对象被回收的时机

代码示例

// 创建引用队列
ReferenceQueue<Object> queue = new ReferenceQueue<>();

// 创建虚引用(必须关联队列)
PhantomReference<Object> phantomRef = 
    new PhantomReference<>(new Object(), queue);

// 永远返回null(与其他引用不同)
System.out.println(phantomRef.get()); // null

// 监控回收(通常另启线程检查队列)
new Thread(() -> {
    try {
        Reference<?> ref = queue.remove();
        System.out.println("对象被回收了:" + ref);
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    }
}).start();

典型应用

  • NIO的DirectByteBuffer清理(通过Cleaner机制)
  • 资源精确释放(如知道某大对象何时被回收后执行清理)

6. 引用队列(ReferenceQueue)

所有引用类型都可以关联引用队列,用于跟踪引用对象的状态变化:


ReferenceQueue<Object> queue = new ReferenceQueue<>();

// 创建带队列的弱引用
WeakReference<Object> ref = 
    new WeakReference<>(new Object(), queue);

System.gc();

// 检查队列(非阻塞)
Reference<?> polledRef = queue.poll();
if(polledRef != null) {
    System.out.println("对象已被回收");
}

7. 四种引用的GC行为对比

引用类型get()行为是否入队列典型GC时机
强引用返回对象不适用永不回收
软引用可能返回null内存不足时入队内存不足时
弱引用可能返回nullGC后入队下次GC
虚引用永远返回nullGC后入队不确定(最优先回收)

8. 实战建议

  1. 缓存选择

    • 需要长期缓存 → 软引用
    • 临时缓存 → 弱引用
  2. 内存泄漏排查

    // 检查弱引用是否异常存活
    WeakReference<Object> ref = new WeakReference<>(suspectObj);
    System.gc();
    if(ref.get() != null) {
        System.out.println("存在强引用持有!");
    }
    

相关文章:

  • 【34期获取股票数据API接口】如何用Python、Java等五种主流语言实例演示获取股票行情api接口之沪深A股当天分时成交数据及接口API说明文档
  • SpringBoot启动run方法分析
  • 配置管理:夯实软件开发与运维根基
  • 实体类设计规范
  • [Deep-ML]Transpose of a Matrix(矩阵的转置)
  • HikariCP 源码核心设计解析与 ZKmall开源商城场景调优实践
  • 【LLM】MCP(Python):实现 stdio 通信的Client与Server
  • 经典算法 a^b
  • FreeRTOS 软件定时器工作原理及应用
  • 【嵌入式学习5】PyQt布局- 信号和槽 - 按钮 - 对话框 - 面向对象
  • 无招回归阿里
  • Linux系统线程
  • es中节点类型有哪些
  • npm 项目命名规则
  • innodb如何实现mvcc的
  • 【JS】使用滑动窗口得到无重复字符的最长子串
  • Linux系统高级IO
  • 还是主题混合程序设计
  • Redash:一个开源的数据查询与可视化工具
  • 如何查看 MySQL 的磁盘空间使用情况:从表级到数据库级的分析