/**
* Timestamp clock, updated by the garbage collector
*///GC 会更新这一个静态变量的值staticprivatelong 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.
*///每次调用get方法时会更新timestampe
// this.timestamp = clock;privatelong timestamp;
private T referent; /* Treated specially by GC */
ReferenceQueue<? super T> queue;
Reference next;
transientprivate Reference discovered; /* used by VM */staticprivateclass Lock { };
privatestatic Lock lock = new Lock();
最有意思的是有段static的代码块
/* List of References waiting to be enqueued. The collector adds
* References to this list, while the Reference-handler thread removes
* them. This list is protected by the above lock object.
*///static类型,全局只有一个,GC一个Reference时,会把该Reference放到pending中,由于Reference有一个next属性,该处可能会是一些被GC过的引用的队列privatestatic Reference pending = null;
/* High-priority thread to enqueue pending References
*/privatestaticclass ReferenceHandler extends Thread {
ReferenceHandler(ThreadGroup g, String name) {
super(g, name);
}
publicvoid run() {
for (;;) {
Reference r;
synchronized (lock) {
if (pending != null) {
//若pending不为null,将每个reference取出,
r = pending;
Reference rn = r.next;
pending = (rn == r) ? null : rn;
r.next = r;
} else {
//若pending为null,等侍try {
lock.wait();
} catch (InterruptedException x) { }
continue;
}
}
// Fast path for cleanersif (r instanceof Cleaner) {
((Cleaner)r).clean();
continue;
}
ReferenceQueue q = r.queue;
//找到该Reference对象中的Queue,将自己添加到ReferenceQueue中
//这样就实现了软引用对象被回收后,在ReferenceQueue中就可以获取到。if (q != ReferenceQueue.NULL) q.enqueue(r);
}
}
}
//启动一个线程(Reference Handler)处理引用static {
ThreadGroup tg = Thread.currentThread().getThreadGroup();
for (ThreadGroup tgn = tg;
tgn != null;
tg = tgn, tgn = tg.getParent());
Thread handler = new ReferenceHandler(tg, "Reference Handler");
/* If there were a special system-only priority greater than
* MAX_PRIORITY, it would be used here
*/
handler.setPriority(Thread.MAX_PRIORITY);
handler.setDaemon(true);
handler.start();
}
其它的一些操作如:get, clear, isEnqueued, enqueue,都是简单的操作。
WeakReference
WeakReference也继承了Reference对象。
WeakReference与SoftReference
这两上类都继承了Reference对象,基本的操作都一样的。唯一的区别就是SoftReference内部的属性(private long timestamp; 在每次get的时候会更新该值),VM有可能要GC的时候使用该字段来判断。这就和两类引用的区别相关连了,WeakReference每次GC时就会直接回收该引用的对象,而SoftReference只有在内存不够用的时候才会回收对象,而回收哪一个对象,可能就需要这个字段来区分。
FinalReference
class FinalReferenceextends Reference {
public FinalReference(T referent, ReferenceQueue<? super T> q) {
super(referent, q);
}
}