java Reference

相关讲解,参考:

Java Reference 源码分析

Java Reference详解

Reference:

// 名称说明下:Reference指代引用对象本身,Referent指代被引用对象
/**
 * Reference的抽象基类,这个类中定义了所有引用对象的常用操作。
 * 由于引用对象是通过与垃圾回收器密切合作来实现的,因此,不要直接继承此基类;
 * 
 * @since 1.2
 */
public abstract class Reference<T> {

    /*
     * 一个Reference实例总是处于以下4种状态之一:
     *
     * 1.Active:Active状态的Reference会受到GC的特别关注,当GC察觉到引用的可达性变化为相应的(appropriate)状态
     * 之后,它的状态将变化为Pending或Inactive;
     * 如果该实例在创建时注册了ReferenceQueue,那么变为Pendging状态,并且添加这个实例到pending-Reference list;
     * 否则变为Inactive状态; 新建的Reference对象都为Active状态; 
     * 此时,queue = 创建实例时注册的 ReferenceQueue 或 ReferenceQueue.NULL; next = null;
     * 
     * 2.Pending:在pending-Reference list中时为该状态,等待被Reference-handler 线程添加
     * 其对应的ReferenceQueue中;
     * 此时,queue = 创建实例时注册的 ReferenceQueue; next = queue中的下一个元素 或 自身;
     * 
     * 3.Enqueued:在ReferenceQueue中时为该状态.被从该ReferenceQueue中移除时变为Inactive状态;
     * 此时,queue = ReferenceQueue.ENQUEUED; next = queue中的下一个元素 或 自身;
     *
     * 4.Inactive:一旦一个实例变为Inactive,则这个状态永远都不会再被改变;
     * queue = ReferenceQueue.NULL; next = this.
     */
     // Reference构造方法默认会注册ReferenceQueue.NULL,所有目前不存在从Active直接到Inactive的状态转变


    // 该reference指向的具体对象
    private T referent; /* Treated specially by GC */

    ReferenceQueue<? super T> queue;

    Reference next;
    transient private Reference<T> discovered; /* used by VM */

    static private class Lock {
    };

    private static Lock lock = new Lock();

    // 由JVM来赋值的,当Reference内部的referent对象的可达状态发生改变,且注册了ReferenceQueue时,
    // JVM会将Reference对象放入到pending链表中,等待被添加进其对应的ReferenceQueue中;
    // ReferenceHandler 不停从这个里面取 reference,加到对应的 ReferenceQueue 中;
    // 该链表的所有访问都是在获取锁lock的时候
    private static Reference pending = null;

    // 高优先级线程,用于将pending链表中的reference添加到其ReferenceQueue队列中
    private static class ReferenceHandler extends Thread {

        ReferenceHandler(ThreadGroup g, String name) {
            super(g, name);
        }

        public void run() {
            for (;;) {

                Reference r;
                synchronized (lock) {
                    // pending list中有值,取出来
                    if (pending != null) {
                        r = pending;
                        Reference rn = r.next;
                        // 重置新pending
                        pending = (rn == r) ? null : rn;
                        // 设置next为自身
                        r.next = r;
                    } else {
                        try {
                            // 等待,直到被唤醒
                            lock.wait();
                        } catch (InterruptedException x) {
                        }
                        // 唤醒后,取下一个
                        continue;
                    }
                }

                // Fast path for cleaners
                if (r instanceof Cleaner) {
                    ((Cleaner) r).clean();
                    continue;
                }
                // 将从 pending list 中取出的reference添加到其对应的ReferenceQueue中
                ReferenceQueue q = r.queue;
                if (q != ReferenceQueue.NULL)
                    q.enqueue(r);
            }
        }
    }

    // 启动 ReferenceHandler 线程
    static {
        ThreadGroup tg = Thread.currentThread().getThreadGroup();
        for (ThreadGroup tgn = tg; tgn != null; tg = tgn, tgn = tg.getParent())
            ;
        Thread handler = new ReferenceHandler(tg, "Reference Handler");
        handler.setPriority(Thread.MAX_PRIORITY);
        handler.setDaemon(true);
        handler.start();
    }

    /* -- Referent accessor and setters -- */

    // 返回Reference指向的对象,如果指向的对象被回收,返回null
    public T get() {
        return this.referent;
    }

    // 清除对指向的对象的引用;不会将reference添加到队列中;
    // gc回收时会直接将referent置为null,不会调用该方法.
    public void clear() {
        this.referent = null;
    }

    /* -- Queue operations -- */

    public boolean isEnqueued() {
        synchronized (this) {
            return (this.queue != ReferenceQueue.NULL) && (this.next != null);
        }
    }

    public boolean enqueue() {
        return this.queue.enqueue(this);
    }

    /* -- Constructors -- */
    Reference(T referent) {
        this(referent, null);
    }

    Reference(T referent, ReferenceQueue<? super T> queue) {
        this.referent = referent;
        // 默认队列 ReferenceQueue.NULL
        this.queue = (queue == null) ? ReferenceQueue.NULL : queue;
    }

}

ReferenceQueue:

/**
 * Reference queues,在检测到Reference对象发生了相应的(appropriate)可达性改变后,
 * 垃圾回收器就将已注册的引用对象添加到对应的ReferenceQueue中。
 * 单向队列:但是其更行为是一个栈,LIFO;插入元素时使用头插法,取出元素时取出队列头;
 * 队列的节点为Reference对象;
 * 
 * @since 1.2
 */
public class ReferenceQueue<T> {

    public ReferenceQueue() {
    }

    private static class Null<S> extends ReferenceQueue<S> {
        boolean enqueue(Reference<? extends S> r) {
            return false;
        }
    }

    // 当我们构造Reference实例时queue传入null时,会默认使用NULL
    static ReferenceQueue<Object> NULL = new Null<>();
    // 防止重复入队,reference入队后会把其queue字段赋值为ENQUEUED,当再次入队时会直接返回失败。
    static ReferenceQueue<Object> ENQUEUED = new Null<>();

    static private class Lock {
    };

    private Lock lock = new Lock();
    private volatile Reference<? extends T> head = null;
    private long queueLength = 0;

    boolean enqueue(Reference<? extends T> r) { /* Called only by Reference class */
        synchronized (lock) {
            ReferenceQueue<?> queue = r.queue;
            // 判断是否传入的引用没有ReferenceQueue || 已经入队
            if ((queue == NULL) || (queue == ENQUEUED)) {
                return false;
            }
            assert queue == this;
            // 入队之后,将引用的队列改为ENQUEUED,作为标志位
            // 状态切为ENQUEUED状态
            r.queue = ENQUEUED;
            // 如果队列中只有一个元素,那么这个元素的next指向自身;
            // 头插法;
            r.next = (head == null) ? r : head;
            head = r;
            queueLength++;
            if (r instanceof FinalReference) {
                sun.misc.VM.addFinalRefCount(1);
            }
            lock.notifyAll();
            return true;
        }
    }

    @SuppressWarnings("unchecked")
    private Reference<? extends T> reallyPoll() { /* Must hold lock */
        // 取出队列头返回
        Reference<? extends T> r = head;
        if (r != null) {
            // 重置新head
            head = (r.next == r) ? null : r.next; // Unchecked due to the next field having a raw type in Reference
            // 状态切为INACTIVE状态
            r.queue = NULL;
            r.next = r;
            queueLength--;
            // FinalReference特殊处理,暂不了解
            if (r instanceof FinalReference) {
                sun.misc.VM.addFinalRefCount(-1);
            }
            return r;
        }
        return null;
    }

    // 如果存在可用的Reference对象,返回该对象;否则返回null;
    public Reference<? extends T> poll() {
        if (head == null)
            return null;
        synchronized (lock) {
            return reallyPoll();
        }
    }

    // 阻塞等待提取队列元素
    // 如果指定的timeout没有获取到reference,返回null;
    // 如果timeout为0,无限期等待,知道获取到reference;
    // timeout单位为ms;
    public Reference<? extends T> remove(long timeout) throws IllegalArgumentException, InterruptedException {
        if (timeout < 0) {
            throw new IllegalArgumentException("Negative timeout value");
        }
        synchronized (lock) {
            Reference<? extends T> r = reallyPoll();
            if (r != null)
                return r;
            long start = (timeout == 0) ? 0 : System.nanoTime();
            for (;;) {
                lock.wait(timeout);
                r = reallyPoll();
                if (r != null)
                    return r;
                if (timeout != 0) {
                    long end = System.nanoTime();
                    timeout -= (end - start) / 1000_000;
                    if (timeout <= 0)
                        return null;
                    start = end;
                }
            }
        }
    }

    public Reference<? extends T> remove() throws InterruptedException {
        return remove(0);
    }

}

SoftReference:

/**
 * SoftReference 指向的对象,在内存不足时会被GC回收; Soft 通常被用于实现
 * 内存敏感(memory-sensitive)的缓存(cache);
 * 在抛出 OOM 之前,虚拟机会保证所有的 softly-reachable 对象被回收;
 * 某些虚拟机可能倾向于不清除(bias against)
 * 最近创建(recently-created)或最近使用过(recently-used)的soft references
 * 指向的对象;
 *
 * @since 1.2
 */
public class SoftReference<T> extends Reference<T> {

    // 由虚拟机更新该时间戳
    static private long clock;

    // 调用get()时会更新,虚拟机可能(只是可能)使用这个域
    // 作为选择softreference对象进行清除的依据
    private long timestamp;

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

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

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

}

WeakReference:

/**
 * weakreference 不影响GC回收 其指向的实例;
 * 如果一个对象为 weakly reachable,虚拟机会将到这个对象的所有weakreference添加到其注册的referencequeue中
 * @since    1.2
 */
public class WeakReference<T> extends Reference<T> {

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

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

}

PhantomReference:

/**
 * 指向的referent如果被回收,该PhantomReference将被添加到其指定的ReferenceQueue中
 * 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.
 * @since    1.2
 */
// 从文档描述上来看,这个类除了阻止GC正常回收外,没什么用,因为无法获取到指向的对象
// phantom  /'fæntəm/ :幽灵;幻影;虚位;幽灵的;幻觉的;有名无实的
// You know it is somewhere,but you never know where
// 这个引用,是没有灵魂的
public class PhantomReference<T> extends Reference<T> {

    // get()方法永远返回null
    public T get() {
        return null;
    }

    // PhantomReference 必须和 ReferenceQueue 一起使用
    // 如果这里的queue也可以传入一个null,这个PhantomReference完全没用(completely useless)
    public PhantomReference(T referent, ReferenceQueue<? super T> q) {
        super(referent, q);
    }

}
原文地址:https://www.cnblogs.com/jamesvoid/p/10127339.html