java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java引用类型

详解Java中的四种引用类型(强软弱虚)

作者:闲不住的码

Java中的引用类型主要分为四种,分别是强引用、软引用、弱引用和虚引用,这篇文章主要为大家详细介绍了四者的使用与区别,需要的小伙伴可以参考下

强引用(StrongReference)

强引用指的就是代码中普遍存在的赋值方式,比如A a = new A()这种。强引用关联的对象,永远不会被GC回收。

当内存空间不足的时候,java虚拟机宁愿抛出OutOfMemoryError 错误,是程序异常终止,也不会回收具有强引用的对象来解决内存不足的问题

obj=null //帮助垃圾回收器回收这个对象

显式地设置obj为null,或者说超出对象的生命周期范围,则GC认为该对象不存在引用,这时候就可以回收这个对象了,具体什么时候回收这要看GC的算法是怎么样的。

当一个方法的内部有一个强引用,这个引用保存在栈中,而这个引用的内容存放在堆中,当这个方法运行完成后就会退出方法栈,那么引用内容也会跟着就会不存在了,这个Object就会被回收。但是如果个这个obj是一个全局变量的时候,就需要再不用的时候将赋值为null,因为强引用是不会被垃圾回收的

在ArrayList的clear方法中就用到了强引用

private transient Object[] elementData;
 
public void clear() {
    modCount++;
     // clear to let GC do its work
    for (int i = 0; i < size; i++) {
        elementData[i] = null;
    }
    size = 0;
}

在 ArrayList 类中定义了一个私有的变量 elementData 数组,在调用方法清空数组时可以看到为每个数组内容赋值为null。 不同于elementData = null,强引用仍然存在,避免在后续调用 add()等方法添加元素时,进行重新的内存分配。使用如 clear() 方法中释放内存的方法对数组中存放的引用类型特别适用,这样就可以及时释放内存。

软引用(SoftReference)

软引用可以用SoftReference来描述,指的是那些有用但是不是必须要的对象。系统在发生内存溢出前会对这类引用的对象进行回收。

软引用可以用来实现内存敏感的高速缓存

软引用自身不会被垃圾回收,因为GC Root还引用着,软引用自身需要配合引用队列来释放。

String str = new String("abc"); // 强引用
SoftReference<String> softRef = new SoftReference<String>(str); // 软引用  
// 当内存不足时,等价于:
if (JVM.内存不足()) {//当内存不够的时候就回收
   str = null;  // 转换为软引用
   System.gc(); // 垃圾回收器进行回收
}

软引用在实际中有重要的应用:

浏览器的后退按钮。按后退时,这个后退时显示的网页内容是重新进行请求还是从缓存中取出呢?这就要看具体的实现策略了。

软引用可以和一个引用队列(ReferenceQueue)联合使用,当引用的对象被垃圾回收器回收后,JVM会自动把这个软引用加入到和它相关的这个引用队列中

弱引用(WeakReference)

弱引用可以用WeakReference来描述,他的强度比软引用更低一点弱引用的对象下一次GC的时候一定会被回收,而不管内存是否足够。 不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。

弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。

String str = new String("abc"); //强引用
WeakReference<String> weakRef = new WeakReference<String>(str); // 弱引用
str = null;
 
// 当垃圾回收器进行扫描回收时等价于:
str = null;
System.gc(); // 垃圾回收器进行回收
 
// 下面的代码会让str再次变为一个强引用:
str = weakRef.get();

使用场景:

弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。

虚引用(PhantomReference)

虚引用也被称作幻影引用,是最弱的引用关系,可以用PhantomReference来描述,他必须和ReferenceQueue一起使用,同样的当发生GC的时候,虚引用也会被回收。

虚引用与其他几种引用都不同,它并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。

虚引用与软引用和弱引用的一个区别在于: 虚引用必须和引用队列 (ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。

应用场景:

Reference和ReferenceQueue

四大引用的父类Reference和ReferenceQueue

在Reference中有5个非常重要的属性:referent,next,discovered,pending,queue。

//5个非常重要的属性
private T referent;         /* Treated specially by GC */
volatile ReferenceQueue<? super T> queue;
Reference next;
transient private Reference<T> discovered;  /* used by VM */
private static Reference<Object> pending = null;

可以把每个Reference看做一个节点,多个Reference通过next,discovered,pending 进行关联

四大状态

上图就是Reference 的四个状态

  //Reference的两个构造方法,一个带队列,一个不带
Reference(T referent) { 
        this(referent, null);
    }
​
    Reference(T referent, ReferenceQueue<? super T> queue) {
        this.referent = referent;
        this.queue = (queue == null) ? ReferenceQueue.NULL : queue;
    }
​

对于带ReferenceQueue的Reference,GC会把要回收对象的Reference放到ReferenceQueue中,后续该Reference需要程序员自己处理 (调用poll方法)

不带ReferenceQueue的Reference, 由GC自己处理,待回收的对象其Reference状态会变成Inactive。

这就是Reference的一个完整的生命周期。

三个Queue/List

三个Queue/List:ReferenceQueue,discovered List和pending List

总结

Java的四种引用的级别由高到低依次为:强引用 > 软引用 > 弱引用 > 虚引用

回收时机用途生存时间
重来不会对象的一般状态JVM停止运行时终止
内存不足 时联合引用队列构造有效期短、占内存大,生命周期长的对象的二级高速缓冲器(内存不足的时候清空)内存不足 时终止
在垃圾回收时联合引用队列构造有效期短、占内存大,生命周期长的对象的一级高速缓冲器(发生GC的时候清空)GC运行后终止
在垃圾回收时联合引用队列来跟踪对象被垃圾回收器回收的活动GC运行后终止

以上就是详解Java中的四种引用类型(强软弱虚)的详细内容,更多关于Java引用类型的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文