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