软引用、弱引用和虚引用

一般来说,我们创建一个一般的对象,如:
Cow cow = new Cow();
这就是变量cow就是强引用,是强可触及的,和所有局部变量一样,对垃圾收集器来说,这是一个根节点。
#垃圾收集器的根节点的引用和强引用的对象包含的引用都是强引用。

在java的源码中,有这么几个类

-java.lang.ref
 +SoftReference.java
 +WeakReference.java
 +PhantomReference.java
 +ReferenceQueue.java
 +Reference.java

其中,软引用(SoftReference)、弱引用(WeakReference)和虚引用(PhantomReference),
它们都继承父类Reference,都有泛型,T即为它们封装的对象t,可以通过构造函数来传封装对象t;
ReferenceQueue是Reference的一个属性域,可通过构造函数来传这个域值,当垃圾收集器要回收封装对象T,会调用
父类Reference的clear(),这样可以切断封装对象跟引用对象的关系,然后调用ReferenceQueue.enqueue(Reference r)方法添加Reference引用到队列中。
这样,通过父类Reference.isEnqueued()便可知道封装对象是否已经被垃圾收集器回收,
若想取得封装的对象T,可调用父类Reference.get()方法,如果封装对象还没被回收,则会返回非null,不过对于虚引用,get()方法总会返回null的,这点需要注意。

##软引用对象
Cow cow = new Cow("niuniu");
java.lang.ref.ReferenceQueue queue = new ReferenceQueue();
java.lang.ref.SoftReference softReference = new SoftReference(cow, queue);
cow = null;
queue = null;

//softReference.clear();
//==>>this.referent = null; this:means SoftReference Object
//softReference.enqueue();
//softReference.isEnqueued();

##弱引用对象
Cow cow2 = new Cow("niuniu2");
ReferenceQueue queue2 = new ReferenceQueue();
java.lang.ref.WeakReference weakReference = new WeakReference(cow2, queue2);
cow2 = null;
queue2 = null;

##虚引用对象
Cow cow3 = new Cow("niuniu3");
ReferenceQueue queue3 = new ReferenceQueue();
java.lang.ref.PhantomReference phantomReference = new PhantomReference(cow3, queue3);
cow3 = null;
queue3 = null;

软可触及的
对象不是强可触及的,即不是强引用的对象,但可以从根节点通过一个或多个(未被清除的)软引用对象触及的。垃圾收集器只有在内存不够时,即会在抛出OutOfMemeryError之前,回收软引用触及的封装对象;
弱可触及的
对象不是强可触及的也不是软可触及的,但可以从根节点通过一个或多个(未被清除的)弱引用对象触及的。垃圾收集器在扫描可回收的对象时,只要扫描到弱引用封装的对象,不管虚拟机的内存够不够用,都定会将该封装的对象回收;java对弱引用,还提供了WeakHashMap来保存弱可触及的对象,其中WeakHashMap的Entry便是继承了WeakReference
private static class Entry extends WeakReference implements Map.Entry {
        V value;
        int hash;
        Entry next;

        /**
         * Creates new entry.
         */
        Entry(Object key, V value,
              ReferenceQueue queue,
              int hash, Entry next) {
            super(key, queue);
            this.value = value;
            this.hash  = hash;
            this.next  = next;
        }
        //...
} 
  
虚可触及的
对象既不是强可触及、软可触及的,也不是弱可触及的,但可以从根节点通过一个或多个(未被清除的)虚引用对象触及的,它和软引用、弱引用区别:它必须有引用队列联合使用,也即是说构造函数必须传ReferenceQueu引用队列。虚引用,在任何时候都可以回收虚引用的封装对象,它跟软引用、弱引用不同,在任何时候,get()方法都会返回null,不过,垃圾收集器会先PhantomReference对象添加到ReferenceQueue队列中,然后再把回收虚可触及的对象,这点也是跟软、弱引用不同的。

你可能感兴趣的:(java)