java Reference

10391 ワード

関連解説、参考:
Java Referenceソースの分析
Java Reference詳細
Reference:
//      :Reference        ,Referent       
/**
 * Reference     ,                  。
 *                        ,  ,         ;
 * 
 * @since 1.2
 */
public abstract class Reference {

    /*
     *   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 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;
    }

}
ReferenceQue:
/**
 * Reference queues,    Reference        (appropriate)      ,
 *                      ReferenceQueue 。
 *     :          ,LIFO;          ,          ;
 *       Reference  ;
 * 
 * @since 1.2
 */
public class ReferenceQueue {

    public ReferenceQueue() {
    }

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

    //      Reference   queue  null ,     NULL
    static ReferenceQueue NULL = new Null<>();
    //       ,reference      queue     ENQUEUED,             。
    static ReferenceQueue 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 extends Reference {

    //           
    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;
    }

}
Weak Reference:
/**
 * weakreference    GC         ;
 *         weakly reachable,             weakreference       referencequeue 
 * @since    1.2
 */
public class WeakReference extends Reference {

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

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

}
PhotomReference:
/**
 *    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 extends Reference {

    // 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);
    }

}