// Reference类
static {
ThreadGroup tg = Thread.currentThread().getThreadGroup();
for (ThreadGroup tgn = tg;
tgn != null;
tg = tgn, tgn = tg.getParent());
// 创建高优先级的Reference Handler线程
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();
// provide access in SharedSecrets
SharedSecrets.setJavaLangRefAccess(new JavaLangRefAccess() {
@Override
public boolean tryHandlePendingReference() {
return tryHandlePending(false);
}
});
} /* High-priority thread to enqueue pending References高优先级的守护线程用来处理GC向pending列表中投入的已经不可达的引用
*/
private static class ReferenceHandler extends Thread {private static void ensureClassInitialized(Class> clazz) {
try {
Class.forName(clazz.getName(), true, clazz.getClassLoader());
} catch (ClassNotFoundException e) {
throw (Error) new NoClassDefFoundError(e.getMessage()).initCause(e);
}
}static {
// pre-load and initialize InterruptedException and Cleaner classes
// so that we don't get into trouble later in the run loop if there's
// memory shortage while loading/initializing them lazily.
ensureClassInitialized(InterruptedException.class);
ensureClassInitialized(Cleaner.class);
}ReferenceHandler(ThreadGroup g, String name) {
super(g, name);
}public void run() {
while (true) {
tryHandlePending(true);
}
}
}// 此属性承载着pending list中的下一个pending的reference,由JVM维护
private static Reference pending = null;
// 高优先级的引用处理线程会死循环的执行此方法
static boolean tryHandlePending(boolean waitForNotify) {
Reference r;
Cleaner c;
try {
synchronized (lock) {
if (pending != null) {
r = pending;
// 'instanceof' might throw OutOfMemoryError sometimes
// so do this before un-linking 'r' from the 'pending' chain...
c = r instanceof Cleaner ? (Cleaner) r : null;
// unlink 'r' from 'pending' chain
pending = r.discovered;
r.discovered = null;
} else {
// The waiting on the lock may cause an OutOfMemoryError
// because it may try to allocate exception objects.
if (waitForNotify) {
// 等待pending list有reference后被JVM唤醒
lock.wait();
}
// retry if waited
return waitForNotify;
}
}
} catch (OutOfMemoryError x) {
// Give other threads CPU time so they hopefully drop some live references
// and GC reclaims some space.
// Also prevent CPU intensive spinning in case 'r instanceof Cleaner' above
// persistently throws OOME for some time...
Thread.yield();
// retry
return true;
} catch (InterruptedException x) {
// retry
return true;
}// Fast path for cleaners
if (c != null) {
// 如果当前处理的reference是Cleaner类型的则执行clean方法
c.clean();
return true;
}// 如果当前处理的reference不是Cleaner类型则加入到queue中
ReferenceQueue super Object> q = r.queue;
if (q != ReferenceQueue.NULL) q.enqueue(r);
return true;
}Reference(T referent, ReferenceQueue super T> queue) {
this.referent = referent;
this.queue = (queue == null) ? ReferenceQueue.NULL : queue;
}// 下边补充软引用与弱引用的实现
public class SoftReference extends Reference {/**
* Timestamp clock, updated by the garbage collector
由GC去更新时钟
*/
static private long 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.
维护一个时间戳,类似于lru,每次调用get方法都会更新此时间戳,JVM可以以这个时间戳为凭证,判断内存不够时选择性的回收那些不常使用的弱引用
*/
private long timestamp;
/**
* Creates a new soft reference that refers to the given object.The new
* reference is not registered with any queue.
*
* @param referent object the new soft reference will refer to
*/
public SoftReference(T referent) {
super(referent);
this.timestamp = clock;
}/**
* Creates a new soft reference that refers to the given object and is
* registered with the given queue.
*
* @param referent object the new soft reference will refer to
* @param q the queue with which the reference is to be registered,
*or null if registration is not required
*
*/
public SoftReference(T referent, ReferenceQueue super T> q) {
super(referent, q);
this.timestamp = clock;
}/**
* Returns this reference object's referent.If this reference object has
* been cleared, either by the program or by the garbage collector, then
* this method returns null.
*
* @returnThe object to which this reference refers, or
*null if this reference object has been cleared
*/
public T get() {
T o = super.get();
if (o != null && this.timestamp != clock)
this.timestamp = clock;
return o;
}}// 弱引用
public class WeakReference extends Reference {/**
* Creates a new weak reference that refers to the given object.The new
* reference is not registered with any queue.
*
* @param referent object the new weak reference will refer to
*/
public WeakReference(T referent) {
super(referent);
}/**
* Creates a new weak reference that refers to the given object and is
* registered with the given queue.
*
* @param referent object the new weak reference will refer to
* @param q the queue with which the reference is to be registered,
*or null if registration is not required
*/
public WeakReference(T referent, ReferenceQueue super T> q) {
super(referent, q);
}}