Java中弱引用和软引用的区别以及虚引用和强引用介绍

 更新时间:2014年04月17日 08:51:19   作者:  
很早Java API就添加了弱引用(WeakReference)和软引用(SoftReference),但并不是所有的程序员都熟悉这两个概念

知道弱引用和软引用的概念与如何使用它们是两码事,引用类在垃圾回收工作的过程中有重要作用。我们都知道垃圾回收器会回收符合回收条件的对象的内存,但并不是所有的程序员都知道回收条件取决于指向该对象的引用类型。这正是Java中弱引用和软引用的主要区别。如果一个对象只有弱引用指向它,垃圾回收器会立即回收该对象,这是一种急切回收方式。相对的,如果有软引用指向这些对象,则只有在JVM需要内存时才回收这些对象。弱引用和软引用的特殊行为使得它们在某些情况下非常有用。例如:软引用可以很好的用来实现缓存,当JVM需要内存时,垃圾回收器就会回收这些只有被软引用指向的对象。而弱引用非常适合存储元数据,例如:存储ClassLoader引用。如果没有类被加载,那么也没有指向ClassLoader的引用。一旦上一次的强引用被去除,只有弱引用的ClassLoader就会被回收。这篇文章中我们将讲述不同类型的Java引用,例如:强引用(Strong Reference)和虚引用(PhantomReference)。

Java中弱引用VS软引用

Java中有如下四种类型的引用:

1.强引用(Strong Reference)
2.弱引用(WeakReference)
3.软引用(SoftReference)
4.虚引用(PhantomReference)

强引用是我们在编程过程中使用的最简单的引用,如代码String s=”abc”中变量s就是字符串对象”abc”的一个强引用。任何被强引用指向的对象都不能被垃圾回收器回收,这些对象都是在程序中需要的。弱引用使用java.lang.ref.WeakReference class 类来表示,你可以使用如下代码创建弱引用:

复制代码 代码如下:

Counter counter = new Counter(); // strong reference - line 1
WeakReference<Counter> weakCounter = new WeakReference<Counter>(counter); //weak reference
counter = null; // now Counter object is eligible for garbage collection

现在只要你给强引用对象counter赋空值null,该对象就可以被垃圾回收器回收。因为该对象此时不再含有其他强引用,即使指向该对象的弱引用weakCounter也无法阻止垃圾回收器对该对象的回收。相反的,如果该对象含有软引用,Counter对象不会立即被回收,除非JVM需要内存。Java中的软引用使用java.lang.ref.SoftReference类来表示,你可以使用如下代码创建软引用:

复制代码 代码如下:

Counter prime = new Counter(); // prime holds a strong reference – line 2
SoftReference soft = new SoftReference(prime) ; //soft reference variable has SoftReference to Counter Object created at line 2

prime = null; // now Counter object is eligible for garbage collection but only be collected when JVM absolutely needs memory

强引用置空之后,代码的第二行为对象Counter创建了一个软引用,该引用同样不能阻止垃圾回收器回收对象,但是可以延迟回收,与弱引用中急切回收对象不同。鉴于软引用和弱引用的这一区别,软引用更适用于缓存机制,而弱引用更适用于存贮元数据。另一个使用弱引用的例子是WeakHashMap,它是除HashMap和TreeMap之外,Map接口的另一种实现。WeakHashMap有一个特点:map中的键值(keys)都被封装成弱引用,也就是说一旦强引用被删除,WeakHashMap内部的弱引用就无法阻止该对象被垃圾回收器回收。

虚引用是java.lang.ref package包中第三种可用的引用,使用java.lang.ref.PhantomReference类来表示。拥有虚引用的对象可以在任何时候被垃圾回收器回收。和弱引用和软引用相似,你可以通过如下代码创建虚引用:

复制代码 代码如下:

DigitalCounter digit = new DigitalCounter(); // digit reference variable has strong reference – line 3
PhantomReference phantom = new PhantomReference(digit); // phantom reference to object created at line 3

digit = null;

一旦移除强引用,第三行的DigitalCounter对象可以在任何时候被垃圾回收器回收。因为只有一个虚引用指向该对象,而虚引用无法阻止垃圾回收器回收对象。

除了了解弱引用、软引用、虚引用和WeakHashMap,还需要了解ReferenceQueue。在创建任何弱引用、软引用和虚引用的过程中你可以通过如下代码提供引用队列ReferenceQueue:

复制代码 代码如下:

ReferenceQueue refQueue = new ReferenceQueue(); //reference will be stored in this queue for cleanup
DigitalCounter digit = new DigitalCounter();
PhantomReference<DigitalCounter> phantom = new PhantomReference<DigitalCounter>(digit, refQueue);

引用实例被添加在引用队列中,你可以再任何时候通过查询引用队列回收对象。一个对象的生命周期可以通过下图进行描述:

 

这就是Java中弱引用和软引用的区别。我们还学到了一些基本的引用类:弱引用、软引用、虚引用以及WeakHashMap和WeakHashMap。总之,合理的使用引用可以帮助垃圾回收器更好的管理Java内存。

相关文章

  • java中各种类型用Stream流求最大值最小值方式

    java中各种类型用Stream流求最大值最小值方式

    这篇文章主要介绍了java中各种类型用Stream流求最大值最小值方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-06-06
  • spring boot教程之产生的背景及其优势

    spring boot教程之产生的背景及其优势

    这篇文章主要介绍了spring boot教程之产生的背景及其优势的相关资料,需要的朋友可以参考下
    2022-08-08
  • Java 基础:string中的compareTo方法

    Java 基础:string中的compareTo方法

    这篇文章主要介绍了Java 基础:string中的compareTo方法,文章围绕string中的compareTo方法的相关资料展开文章详细内容,希望对待大家有所帮助
    2021-12-12
  • Spring成为Java开发的标准以及SpringBoot如何彻底改变开发体验

    Spring成为Java开发的标准以及SpringBoot如何彻底改变开发体验

    本文深入剖析了Spring框架及其在Java企业级应用开发中的地位,强调了Spring通过IoC容器、AOP和模块化生态系统等核心特性,解决了一系列传统JavaEE开发的痛点,本文给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧
    2025-12-12
  • springSecurity过滤web请求的项目实践

    springSecurity过滤web请求的项目实践

    SpringSecurity是一个功能强大的安全框架,提供了全面的 Web 安全功能,它的核心之一是过滤器链,用于拦截和处理 Web 请求,本文就来介绍SpringSecurity配置和使用过滤器来管理Web请求的安全性,感兴趣的可以了解一下
    2025-09-09
  • Kafka消费客户端协调器GroupCoordinator详解

    Kafka消费客户端协调器GroupCoordinator详解

    这篇文章主要为大家介绍了Kafka消费客户端协调器GroupCoordinator使用示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-10-10
  • java二维数组遍历的2种代码

    java二维数组遍历的2种代码

    这篇文章主要介绍了java二维数组遍历的2种代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-07-07
  • SpringBoot的@Value注解如何设置默认值

    SpringBoot的@Value注解如何设置默认值

    这篇文章主要介绍了SpringBoot的@Value注解如何设置默认值问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-02-02
  • mybatis plus in方法使用详解

    mybatis plus in方法使用详解

    这篇文章主要介绍了mybatis plus in方法使用详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-04-04
  • SpringBoot整合spring-retry实现接口请求重试机制及注意事项

    SpringBoot整合spring-retry实现接口请求重试机制及注意事项

    今天通过本文给大家介绍我们应该如何使用SpringBoot来整合spring-retry组件实现重试机制及注意事项,本文通过实例代码给大家介绍的非常详细,需要的朋友参考下吧
    2021-08-08

最新评论