垃圾回收的原理是根据对象的可达性来决定是否回收该对象。对象可达或者说可获得的,是指对象可在应用中的某处找到,这意味着在栈中有一个引用指向此对象;也有可能是一个引用指向的对象中包含一个引用指向此对象;也有可能中间有更多的连接。如果一个对象是可获得的,那么垃圾回收器就不能释放它,如果一个对象是不可获得的,释放该对象就不会存在问题。

如果想持有某个对象的引用,希望以后还可以继续访问到该对象,但是也希望能够允许垃圾回收器释放它,此时就应该想到Reference。这样,你就可以继续使用该对象,并在内存耗尽前释放该对象。

以Reference对象作为和普通引用之间的媒介。另外,一定不能有普通的引用指向那个对象,这样才能达到上述目的。

SoftReference,WeakReference和PhantomReference由强到弱排列,强弱是指可获得性,更易失可获得性。其中SoftReference是泳衣实现内存敏感的告诉缓存,在抛出OutOfMemoryError之前保证会调用垃圾回收器清理此类引用。WeakReference是为实现规范映射而设计的,它不妨碍垃圾回收器回收映射的键或者值。规范映射的对象实例可以在多处被同时使用,其中Thread中用以保存审计的类使用的WeakClassKey便是继承自WeakReference。PhantomReference用以调度回收前的清理工作,比java终止机制更灵活。与soft和weak不同,phantomReferen的get方法总是返回null,并且,它不是由垃圾回收器自动清理,那么这个类还能干啥用呢,主要是做一些回收前的清理工作,类似finalize方法。

下面一段代码:执行gc前后对比soft和weak,soft并没有被回收,而weak被回收并被放入referencequeue

import java.lang.ref.*;
import java.util.LinkedList;


class VeryBig{
    private static final int SIZE=10000;
    private long[] la = new long[SIZE];
    private String ident;
    public VeryBig(String id){
        this.ident = id;
    }

    @Override
    public String toString() {
        return this.ident;
    }
    protected void finalize(){
        System.out.println("Finalizing " + ident);
    }
}

public class NesttyMain {

    private static ReferenceQueue<VeryBig> rq = new ReferenceQueue<VeryBig>();

    public static void checkQueue(){
        Reference<? extends VeryBig>  inq = rq.poll();
        if(inq!=null){
            System.out.println("In queue: "+inq.get());
        }
    }

    public static void main(String[] args){
        int size=10;
        LinkedList<SoftReference<VeryBig>> sa = new LinkedList<SoftReference<VeryBig>>();
        for (int i=0;i<size;i++){
            sa.add(new SoftReference<VeryBig>(new VeryBig("Soft"+i),rq));
            System.out.println("Just created: "+sa.getLast());
            checkQueue();
        }

        LinkedList<WeakReference<VeryBig>> wa = new LinkedList<WeakReference<VeryBig>>();
        for (int i=0;i<size;i++){
            wa.add(new WeakReference<VeryBig>(new VeryBig("Weak"+i),rq));
            System.out.println("Just created: "+wa.getLast());
            checkQueue();
        }

        SoftReference<VeryBig> s = new SoftReference<VeryBig>(new VeryBig("Soft"));
        WeakReference<VeryBig> a = new WeakReference<VeryBig>(new VeryBig("Weak"));
        //此处执行gc后weakreference的linkedlist被回收,回收对象被存放到rq中,在下面执行phantom的checkqueue打印的就是weakreference
        //执行get返回的是null
        System.gc();

        LinkedList<PhantomReference<VeryBig>> pa = new LinkedList<PhantomReference<VeryBig>>();
        for (int i=0;i<size;i++){
            pa.add(new PhantomReference<VeryBig>(new VeryBig("Phantom"+i),rq));
            System.out.println("Just created: "+pa.getLast());
            checkQueue();
        }


    }

}

输出:


Just created: java.lang.ref.SoftReference@61bbe9ba
Just created: java.lang.ref.SoftReference@610455d6
Just created: java.lang.ref.SoftReference@511d50c0
Just created: java.lang.ref.SoftReference@60e53b93
Just created: java.lang.ref.SoftReference@5e2de80c
Just created: java.lang.ref.SoftReference@1d44bcfa
Just created: java.lang.ref.SoftReference@266474c2
Just created: java.lang.ref.SoftReference@6f94fa3e
Just created: java.lang.ref.SoftReference@5e481248
Just created: java.lang.ref.SoftReference@66d3c617
Just created: java.lang.ref.WeakReference@63947c6b
Just created: java.lang.ref.WeakReference@2b193f2d
Just created: java.lang.ref.WeakReference@355da254
Just created: java.lang.ref.WeakReference@4dc63996
Just created: java.lang.ref.WeakReference@d716361
Just created: java.lang.ref.WeakReference@6ff3c5b5
Just created: java.lang.ref.WeakReference@3764951d
Just created: java.lang.ref.WeakReference@4b1210ee
Just created: java.lang.ref.WeakReference@4d7e1886
Just created: java.lang.ref.WeakReference@3cd1a2f1
Just created: java.lang.ref.PhantomReference@2f0e140b
Just created: java.lang.ref.PhantomReference@7440e464
Just created: java.lang.ref.PhantomReference@49476842
In queue: null
Just created: java.lang.ref.PhantomReference@78308db1
In queue: null
Just created: java.lang.ref.PhantomReference@27c170f0
In queue: null
Just created: java.lang.ref.PhantomReference@5451c3a8
In queue: null
Just created: java.lang.ref.PhantomReference@2626b418
In queue: null
Just created: java.lang.ref.PhantomReference@5a07e868
In queue: null
Just created: java.lang.ref.PhantomReference@76ed5528
In queue: null
Just created: java.lang.ref.PhantomReference@2c7b84de
In queue: null
Finalizing Weak
Finalizing Weak9
Finalizing Weak8
Finalizing Weak7
Finalizing Weak6
Finalizing Weak5
Finalizing Weak4
Finalizing Weak3
Finalizing Weak2
Finalizing Weak1
Finalizing Weak0

Process finished with exit code 0
01-04 04:13