package java.lang.ref;
import sun.misc.Cleaner;
/**
* 一個抽象類別,是所有reference類的超類,此類不能直接整合,它與記憶體回收有很緊密的關係
* 用來表示弱引用(weak reference),可以強一個強引用的對象封裝,並使用get()方法重新獲得此對象
* 在此類中的靜態塊中會啟動一個線程,用來輪巡pending對象,使其入隊
*
* comment by liqiang
*
* @author Mark Reinhold
*
*/
public abstract class Reference {
/* 一個引用對象有四個狀態:
*
* Active(有效):此對象有效,他被GC特殊處理,當此對象的可觸及性發生變化時(對此對象的引用), 它將改變成掛起或無效狀態
* 它的對象狀態 queue: 註冊的ReferenceQueue對象(註冊了隊列), ReferenceQueue.NULL(沒有註冊隊列)
* next: null
*
* Pending(掛起):元素等待入隊,沒有註冊隊列的元素不能為此狀態
* 它的對象狀態 queue: 註冊的ReferenceQueue對象(註冊了隊列), ReferenceQueue.NULL(沒有註冊隊列)
* next: 隊列中的下一個對象 如果是隊列中的最後一個對象 next=this
*
* Enqueued(入隊):元素已經入隊,沒有註冊隊列的元素不能為此狀態,當元素從隊列中remove出來的時候,元素狀態變為Inactive
* 它的對象狀態 queue: ReferenceQueue.ENQUEUED
* next: 隊列中的下一個對象 如果是隊列中的最後一個對象 next=this
*
* Inactive(無效):表示此引用不可用,元素為此狀態時它的狀態不可改變
* 它的對象狀態 queue = ReferenceQueue.NULL;
* next = this.
*
* GC判斷next狀態,如果next=null則為Active狀態,否則需要對它進行特殊處理
*
*/
//此引用對象封裝的對象
private Object referent;
//引用對象的隊列
ReferenceQueue queue;
//下一個元素
Reference next;
//虛擬機器使用
transient private Reference discovered;
//一個靜態內部類 表示鎖
static private class Lock { };
private static Lock lock = new Lock();
//等待入隊的元素列
private static Reference pending = null;
//此線程在類裝載時啟動,用來將pending的元素入隊
private static class ReferenceHandler extends Thread {
ReferenceHandler(ThreadGroup g, String name) {
super(g, name);
}
public void run() {
for (;;) {
Reference r;
//lock是一個靜態對象,線程也是在static塊中啟動的,所以所有的
//此refence類都只有一個線程,和鎖,此鎖的目的是保護此對象中的同步地區塊內的資料
synchronized (lock) {
if (pending != null) {
//如果pending不為null取出此對象
r = pending;
Reference rn = r.next;
//將原pending的下一個元素,賦給當前的pending
//如果原pending的下一個元素為自己,則當前pending=null
pending = (rn == r) ? null : rn;
r.next = r;
} else {
try {
//如果沒有pending對象則阻塞線程
lock.wait();
} catch (InterruptedException x) { }
continue;
}
}
// Fast path for cleaners
if (r instanceof Cleaner) {
((Cleaner)r).clean();
continue;
}
ReferenceQueue q = r.queue;
//如果當前元素已經註冊到隊列則入隊
if (q != ReferenceQueue.NULL) q.enqueue(r);
}
}
}
static {
//取得當前線程組
ThreadGroup tg = Thread.currentThread().getThreadGroup();
//取得最上層的System線程組
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 -- */
/**
*
* 返回此應用對象封裝的強引用對象, 如果強引用對象被記憶體回收,或程式調用了此對象的clear方法
* 則返回的對象為null
*
* @return The object to which this reference refers, or
* <code>null</code> if this reference object has been cleared
*/
public Object get() {
return this.referent;
}
/**
*
* 清空它的referent對象,此方法不會將對象入隊
*/
public void clear() {
this.referent = null;
}
/* -- Queue operations -- */
/**
*
* 判斷此對象是否入隊,就是判斷他的內部狀態是否是Pending或Enqueued
*
* @return <code>true</code> if and only if this reference object has
* been enqueued
*/
public boolean isEnqueued() {
/* In terms of the internal states, this predicate actually tests
whether the instance is either Pending or Enqueued */
synchronized (this) {
return (this.queue != ReferenceQueue.NULL) && (this.next != null);
}
}
/**
* Adds this reference object to the queue with which it is registered,
* if any.
*
* 入隊操作
*
* @return ture: 表示入隊成功 false: 表示它已經入隊或沒有註冊隊列
* @return <code>true</code> if this reference object was successfully
* enqueued; <code>false</code> if it was already enqueued or if
* it was not registered with a queue when it was created
*/
public boolean enqueue() {
return this.queue.enqueue(this);
}
/* -- Constructors -- */
//建構函式
Reference(Object referent) {
this(referent, null);
}
//建構函式
Reference(Object referent, ReferenceQueue queue) {
this.referent = referent;
if (referent == null) {
//如果強引用對象為null則標誌此引用對象為 inactive
/* Immediately make this instance inactive */
this.queue = ReferenceQueue.NULL;
this.next = this;
} else {
//初始queue對象,如果不為null直接賦值,為null則賦給ReferenceQueue.NULL
this.queue = (queue == null) ? ReferenceQueue.NULL : queue;
//next = null 表示Active狀態
this.next = null;
}
}
}