从源代码看:为什么可以软引用,弱引用,虚引用

看了那么多关于软引用,弱引用,虚引用的例子,还是从源码开始说起为什么可以这样做吧


软引用 SoftReference

    /**
     * Timestamp clock, updated by the garbage collector
     */
    static private long clock;

    /**
     * Timestamp updated by each invocation of the get method.  The VM may use
     * this field when selecting soft references to be cleared, but it is not
     * required to do so.
     */
    private long timestamp;

与Reference类相比多了两个参数,clock由gc维护,timestamp由虚拟机维护,每次调用更新timestamp

    public SoftReference(T referent) {
        super(referent);
        this.timestamp = clock;
    }

    public SoftReference(T referent, ReferenceQueue<? super T> q) {
        super(referent, q);
        this.timestamp = clock;
    }

采用了两种初始化的方式,在构造函数中设置了timestamp的值

    public T get() {
        T o = super.get();
        if (o != null && this.timestamp != clock)
            this.timestamp = clock;
        return o;
    }

测试代码

SoftReference<String> sr = new SoftReference<String>(
				new String("hello"));
		System.out.println(sr.get());
		System.gc();
		System.out.println(sr.get());

测试结果

hello
hello

get方法首先调用了父类方法获得返回对象,然后修改了timestamp的值为每次调用的时间

在System.gc()调用后,依然可以获取对象的值


弱引用 WeakReference

    public WeakReference(T referent) {
        super(referent);
    }

    public WeakReference(T referent, ReferenceQueue<? super T> q) {
        super(referent, q);
    }


测试代码

WeakReference<String> sr = new WeakReference<String>(
				new String("hello"));

		System.out.println(sr.get());
		System.gc(); // 通知JVM的gc进行垃圾回收
		System.out.println(sr.get());

测试结果

hello
null


弱引用继承了Reference类,实现了两种自己的初始化,其他的方法使用Reference的方法,因此,在System.gc()后输出结果为null



虚引用 PhantomReference


不影响对象生命周期

 * <p> Unlike soft and weak references, phantom references are not
 * automatically cleared by the garbage collector as they are enqueued.  An
 * object that is reachable via phantom references will remain so until all
 * such references are cleared or themselves become unreachable.

从javadoc可以看出来,虚引用不会自动被gc清理,需要相关引用全部清除,或是引用自身不可达的时候才可以被清除

    public T get() {
        return null;
    }

    public PhantomReference(T referent, ReferenceQueue<? super T> q) {
        super(referent, q);
    }

从源代码可以看到,PhantomReference继承了Reference类,初始化的时候把引用添加进了引用队列,在调用get()方法的时候固定返回一个null值


测试代码

ReferenceQueue<String> queue = new ReferenceQueue<String>();
		PhantomReference<String> pr = new PhantomReference<String>(new String(
				"hello"), queue);
		System.out.println(pr.get());
输出结果

null

因此,不经过System.gc(),每次返回的就是一个null


展开阅读全文

没有更多推荐了,返回首页