* Initial states:
*[active/registered]
*[active/unregistered] [1]
*
* Transitions:
*clear
*[active/registered]------->[inactive/registered]
*||
*|| enqueue [2]
*| GCenqueue [2]|
*|-----------------|
*||
*v|
*[pending/registered]---v
*|| ReferenceHandler
*| enqueue [2]|--->[inactive/enqueued]
*v||
*[pending/enqueued]---|
*|| poll/remove
*| poll/remove|
*||
*vReferenceHandlerv
*[pending/dequeued]------>[inactive/dequeued]
*
*
*clear/enqueue/GC [3]
*[active/unregistered]------
*||
*| GC|
*||--> [inactive/unregistered]
*v|
*[pending/unregistered]------
*ReferenceHandler
*
* Terminal states:
*[inactive/dequeued]
*[inactive/unregistered]
*
* Unreachable states (because enqueue also clears):
*[active/enqeued]
*[active/dequeued]
*
* [1] Unregistered is not permitted for FinalReferences.
*
* [2] These transitions are not possible for FinalReferences, making
* [pending/enqueued] and [pending/dequeued] unreachable, and
* [inactive/registered] terminal.
*
* [3] The garbage collector may directly transition a Reference
* from [active/unregistered] to [inactive/unregistered],
* bypassing the pending-Reference list.
Reference示例
如下示例代码所示:
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class ReferenceTest {private static ReferenceQueue queue = new ReferenceQueue<>();
public static void main(String[] args) throws Exception {List> references = new ArrayList<>();
// 创建ReferenceQueue队列
ReferenceQueue queue = new ReferenceQueue<>();
// 创建软引用,只有在GC发现内存不足时才会回收softRef所指向的对象
Object obj = new Object();
SoftReference softRef = new SoftReference<>(obj, queue);
// 创建7个弱引用对象
Object obj1 = new Object();
Object obj2 = new Object();
Object obj3 = new Object();
Object obj4 = new Object();
WeakReference weakRef1 = new WeakReference<>(obj1, queue);
WeakReference weakRef2 = new WeakReference<>(obj2, queue);
WeakReference weakRef3 = new WeakReference<>(obj3, queue);
WeakReference weakRef4 = new WeakReference<>(obj4, queue);
// 将Reference对象本身用强引用保存起来
references.add(softRef);
references.add(weakRef1);
references.add(weakRef2);
references.add(weakRef3);
references.add(weakRef4);
// 将Object对象引用置为null,使得没有强引用指向Object对象
obj1 = null;
obj2 = null;
obj3 = null;
obj4 = null;
// 手动触发GC,obj1、obj2、obj3、obj4四个对象将被回收
System.gc();
TimeUnit.SECONDS.sleep(2);
Reference ref;
while ((ref = queue.poll()) != null) {
System.out.println("reference polled from queue: " + ref);
}
TimeUnit.SECONDS.sleep(1000);
}
}
运行结果如下:
reference polled from queue: java.lang.ref.WeakReference@52a86356
reference polled from queue: java.lang.ref.WeakReference@5ce81285
reference polled from queue: java.lang.ref.WeakReference@78c03f1f
reference polled from queue: java.lang.ref.WeakReference@5ec0a365
/* High-priority thread to enqueue pending References
*/
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 Cleaner class so that we don't
// get into trouble later in the run loop if there's
// memory shortage while loading/initializing it lazily.
ensureClassInitialized(Cleaner.class);
}ReferenceHandler(ThreadGroup g, String name) {
super(g, null, name, 0, false);
}public void run() {
while (true) {
// run方法里不断调用processPendingReferences方法获取pendingList然后入队
processPendingReferences();
}
}
}
ReferenceHandler线程在静态代码块中被创建和启动:
static {
ThreadGroup tg = Thread.currentThread().getThreadGroup();
for (ThreadGroup tgn = tg;
tgn != null;
tg = tgn, tgn = tg.getParent());
// 创建ReferenceHandler线程
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 waitForReferenceProcessing()
throws InterruptedException
{
return Reference.waitForReferenceProcessing();
}@Override
public void runFinalization() {
Finalizer.runFinalization();
}
});
}
如下所示为processPendingReferences方法的实现:
/*
* Atomically get and clear (set to null) the VM's pending-Reference list.
* native方法获取pendingList列表
*/
private static native Reference getAndClearReferencePendingList();
/*
* Wait until the VM's pending-Reference list may be non-null.
* native方法等待获取pendingList列表
*/
private static native void waitForReferencePendingList();
private static final Object processPendingLock = new Object();
private static boolean processPendingActive = false;
private static void processPendingReferences() {
// Only the singleton reference processing thread calls
// waitForReferencePendingList() and getAndClearReferencePendingList().
// These are separate operations to avoid a race with other threads
// that are calling waitForReferenceProcessing().
// 等待获取pendingList列表
waitForReferencePendingList();
Reference pendingList;
synchronized (processPendingLock) {
// 获取pendingList列表
pendingList = getAndClearReferencePendingList();
processPendingActive = true;
}
while (pendingList != null) {
Reference ref = pendingList;
// 获取下一个原对象被GC或即将被GC的对应的Reference对象
pendingList = ref.discovered;
ref.discovered = null;
if (ref instanceof Cleaner) {
((Cleaner)ref).clean();
// Notify any waiters that progress has been made.
// This improves latency for nio.Bits waiters, which
// are the only important ones.
synchronized (processPendingLock) {
processPendingLock.notifyAll();
}
} else {
ReferenceQueue super Object> q = ref.queue;
// 将Reference对象入队
if (q != ReferenceQueue.NULL) q.enqueue(ref);
}
}
// Notify any waiters of completion of current round.
synchronized (processPendingLock) {
processPendingActive = false;
processPendingLock.notifyAll();
}
}
ReferenceQueue的入队代码:
private static class Null extends ReferenceQueue {
boolean enqueue(Reference> r) {
return false;
}
}static final ReferenceQueue NULL = new Null();
static final ReferenceQueue ENQUEUED = new Null();
private static class Lock { };
private final Lock lock = new Lock();
private volatile Reference extends T> head;
private long queueLength = 0;
boolean enqueue(Reference extends T> r) { /* Called only by Reference class */
synchronized (lock) {
// Check that since getting the lock this reference hasn't already been
// enqueued (and even then removed)
ReferenceQueue> queue = r.queue;
// 判断Reference对象是否不需要入队或者已经入队
if ((queue == NULL) || (queue == ENQUEUED)) {
return false;
}
assert queue == this;
// Self-loop end, so if a FinalReference it remains inactive.
// 将Reference对象插入queue的头部,并修改queue的head指向插入的Reference对象
r.next = (head == null) ? r : head;
head = r;
queueLength++;
// Update r.queue *after* adding to list, to avoid race
// with concurrent enqueued checks and fast-path poll().
// Volatiles ensure ordering.
// 将Reference对象的queue属性设置为ENQUEUED,标识Reference对象已经入队
r.queue = ENQUEUED;
if (r instanceof FinalReference) {
VM.addFinalRefCount(1);
}
// 通知其他线程有Reference对象入队了,可以从队列取下元素进行处理了
lock.notifyAll();
return true;
}
}
private static class ReferenceHandler extends Thread {
public void run() {
while (true) {
processPendingReferences();
}
}
}
processPendingReferences方法如下:
private static void processPendingReferences() {
// Only the singleton reference processing thread calls
// waitForReferencePendingList() and getAndClearReferencePendingList().
// These are separate operations to avoid a race with other threads
// that are calling waitForReferenceProcessing().
waitForReferencePendingList();
Reference pendingList;
synchronized (processPendingLock) {
pendingList = getAndClearReferencePendingList();
processPendingActive = true;
}
while (pendingList != null) {
Reference ref = pendingList;
pendingList = ref.discovered;
ref.discovered = null;
// 判断Reference对象的实际类型是否为Cleaner
if (ref instanceof Cleaner) {
// 是的话直接执行clean方法来清理资源
((Cleaner)ref).clean();
// Notify any waiters that progress has been made.
// This improves latency for nio.Bits waiters, which
// are the only important ones.
synchronized (processPendingLock) {
processPendingLock.notifyAll();
}
} else {
// 否则将Reference对象加入到队列中
ReferenceQueue super Object> q = ref.queue;
if (q != ReferenceQueue.NULL) q.enqueue(ref);
}
}
// Notify any waiters of completion of current round.
synchronized (processPendingLock) {
processPendingActive = false;
processPendingLock.notifyAll();
}
}
class FinalReference extends Reference {public FinalReference(T referent, ReferenceQueue super T> q) {
super(referent, q);
}@Override
public boolean enqueue() {
throw new InternalError("should never reach here");
}
}
实现非常简单,enqueue方法直接抛出异常,根据Reference里对enqueue的说明:
/**
* Clears this reference object and adds it to the queue with which
* it is registered, if any.
*
* This method is invoked only by Java code;
when the garbage collector
* enqueues references it does so directly, without invoking this method.
*
* @returntrue if this reference object was successfully
*enqueued;
false if it was already enqueued or if
*it was not registered with a queue when it was created
*/