强引用、软引用、弱引用、虚引用的区别

一、强引用(Strong Reference)

定义
强引用是 Java 中最常见的引用类型,也是默认的引用类型。例如,普通的对象引用就是强引用:

String str = new String("Hello, World!");

在上述代码中,str 是一个强引用,指向堆中的字符串对象 "Hello, World!"

特点

  • GC 不会回收:只要一个对象有强引用存在,垃圾回收器永远不会回收该对象,即使内存不足,JVM 也会宁愿抛出 OutOfMemoryError 异常,也不会回收强引用的对象。
  • 生命周期:对象的生命周期与强引用的生命周期一致,当没有任何强引用指向这个对象时,GC 才会将其回收。

应用场景

  • 强引用广泛用于普通对象引用,是最常用的引用类型。
  • 适用于任何希望对象在应用程序运行期间始终存在的情况。

二、软引用(Soft Reference)

定义
软引用是 Java 中提供的一种较弱的引用类型。它可以通过 java.lang.ref.SoftReference 类来实现:

SoftReference<String> softRef = new SoftReference<>(new String("Soft Reference"));

特点

  • 内存敏感回收:软引用的对象只有在 JVM 判定内存不足时才会被回收。当 JVM 需要更多的内存时,会回收那些只被软引用指向的对象。换句话说,如果内存充足,这些对象可能不会被回收。
  • 延长生命周期:软引用通常用于实现内存敏感的缓存,即缓存中的对象会尽量保持在内存中,直到 JVM 需要更多内存时才会被回收。
  • 垃圾回收顺序:软引用的对象在 GC 时的回收顺序要晚于弱引用和虚引用。

应用场景

  • 缓存:软引用非常适合用于实现缓存。例如,常用的对象可以使用软引用来缓存,从而避免频繁创建对象并节省内存,但当内存紧张时可以自动回收这些缓存对象。
  • 内存优化:对于那些需要占用较多内存的对象,且对象的使用频率不确定,使用软引用是一种有效的内存优化策略。

三、弱引用(Weak Reference)

定义
弱引用是一种比软引用更弱的引用类型。它可以通过 java.lang.ref.WeakReference 类来实现:

WeakReference<String> weakRef = new WeakReference<>(new String("Weak Reference"));

特点

  • GC 优先回收:弱引用的对象在下一次垃圾回收时,只要被发现,都会被回收,即使内存非常充足。换句话说,弱引用的生命周期只比 null 稍长。
  • 弱引用对象的可访问性:如果一个对象只被弱引用指向,那么下次 GC 发生时,该对象就会被回收。
  • 避免内存泄漏:弱引用经常用于避免内存泄漏,尤其是在使用大型对象集合时,通过弱引用可以防止这些对象因为意外的强引用而无法被回收。

应用场景

  • WeakHashMap:这是 JDK 提供的一个典型的弱引用应用,它的键是弱引用,键对象在没有其他强引用时会被 GC 回收,防止内存泄漏。
  • 事件监听器:弱引用通常用于保存事件监听器,防止由于意外的强引用导致监听器对象无法被回收。

四、虚引用(Phantom Reference)

定义
虚引用是最弱的一种引用类型,它可以通过 java.lang.ref.PhantomReference 类来实现:

PhantomReference<String> phantomRef = new PhantomReference<>(new String("Phantom Reference"), referenceQueue);

虚引用必须与引用队列(ReferenceQueue)联合使用,当垃圾回收器准备回收对象时,会将虚引用加入到它的关联队列中。

特点

  • 无法通过虚引用获取对象:调用 get() 方法永远返回 null,因此虚引用本质上是用来跟踪对象被垃圾回收的状态,而不是访问对象。
  • 监控对象的回收:虚引用的主要作用是在对象被回收时执行一些清理操作或记录日志。因此,虚引用常用于实现一些后期清理操作,比如处理资源释放等。
  • 提前处理:虚引用可以确保对象在被彻底从内存中删除前,进行某些特定的操作。

应用场景

  • 管理堆外内存:虚引用在直接内存或堆外内存的管理中非常有用,当对象被垃圾回收器回收时,通过虚引用可以回收相关资源,避免内存泄漏。
  • 实现对象的 finalize 替代方案:由于 finalize 方法不再推荐使用,虚引用可以作为替代方案,确保对象回收前的资源清理。

五、总结

Java 中提供的四种引用类型(强引用、软引用、弱引用、虚引用)在对象生命周期管理中各有其应用场景:

  • 强引用:最常用的引用类型,通常在 JVM 运行期间不会被回收。
  • 软引用:适用于缓存场景,允许 JVM 根据内存状态回收这些引用指向的对象。
  • 弱引用:用于防止内存泄漏,尤其在 WeakHashMap 这样的场景中非常有用。
  • 虚引用:用于在对象被垃圾回收前执行一些特定操作,通常用于监控对象的生命周期,或清理资源。

猜你喜欢

转载自blog.csdn.net/Flying_Fish_roe/article/details/143424288