Abstract base class for reference objects. This class defines the operations common to all reference objects. Because reference objects are implemented in close cooperation with the garbage collector, this class may not be subclassed directly.
/* The queue this reference gets enqueued to by GC notification or by * calling enqueue(). * * When registered: the queue with which this reference is registered. * enqueued: ReferenceQueue.ENQUEUE * dequeued: ReferenceQueue.NULL * unregistered: ReferenceQueue.NULL */ volatile ReferenceQueue<? super T> queue;
next:下一个Reference实例的引用,Reference实例通过此构造单向的链表。
/* The link in a ReferenceQueue's list of Reference objects. * * When registered: null * enqueued: next element in queue (or this if last) * dequeued: this (marking FinalReferences as inactive) * unregistered: null */ @SuppressWarnings("rawtypes") volatile Reference next;
/* When active: next element in a discovered reference list maintained by GC (or this if last) * pending: next element in the pending list (or null if last) * otherwise: NULL */ transientprivate Reference<T> discovered; /* used by VM */
**实例方法(和ReferenceHandler线程不相关的方法)**:
// 获取持有的referent实例 @HotSpotIntrinsicCandidate public T get(){ returnthis.referent; }
static { // 确保Cleaner这个类已经初始化 // 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); }
/* 原子获取(后)并且清理VM中的pending引用链表 * Atomically get and clear (set to null) the VM's pending-Reference list. */ privatestaticnative Reference<Object> getAndClearReferencePendingList();
/* 检验VM中的pending引用对象链表是否有剩余元素 * Test whether the VM's pending-Reference list contains any entries. */ privatestaticnativebooleanhasReferencePendingList();
/* 等待直到pending引用对象链表不为null,此方法阻塞的具体实现又VM实现 * Wait until the VM's pending-Reference list may be non-null. */ privatestaticnativevoidwaitForReferencePendingList();
// 这个是死循环中的核心方法,功能是处理pending链表中的引用元素 privatestaticvoidprocessPendingReferences(){ // 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(). // (1)等待 waitForReferencePendingList(); Reference<Object> pendingList; synchronized (processPendingLock) { // (2)获取并清理,标记处理中状态 pendingList = getAndClearReferencePendingList(); processPendingActive = true; } // (3)通过discovered(下一个元素)遍历pending链表进行处理 while (pendingList != null) { Reference<Object> ref = pendingList; pendingList = ref.discovered; ref.discovered = null; // 如果是Cleaner类型执行执行clean方法并且对锁对象processPendingLock进行唤醒所有阻塞的线程 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 { // 非Cleaner类型并且引用队列不为ReferenceQueue.NULL则进行入队操作 ReferenceQueue<? super Object> q = ref.queue; if (q != ReferenceQueue.NULL) q.enqueue(ref); } } // (4)当次循环结束之前再次唤醒锁对象processPendingLock上阻塞的所有线程 // Notify any waiters of completion of current round. synchronized (processPendingLock) { processPendingActive = false; processPendingLock.notifyAll(); } }
ReferenceHandler线程启动的静态代码块如下:
static { // ThreadGroup继承当前执行线程(一般是主线程)的线程组 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(); // 注意这里覆盖了全局的jdk.internal.misc.JavaLangRefAccess实现 // provide access in SharedSecrets SharedSecrets.setJavaLangRefAccess(new JavaLangRefAccess() { @Override publicbooleanwaitForReferenceProcessing() throws InterruptedException{ return Reference.waitForReferenceProcessing(); }
// 入队操作,只会被Reference实例调用 booleanenqueue(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.NULL或者ReferenceQueue.ENQUEUED则入队失败返回false ReferenceQueue<?> queue = r.queue; if ((queue == NULL) || (queue == ENQUEUED)) { returnfalse; } assert queue == this; // Self-loop end, so if a FinalReference it remains inactive. // 如果链表没有元素,则此引用实例直接作为头节点,否则把前一个引用实例作为下一个节点 r.next = (head == null) ? r : head; // 当前实例更新为头节点,也就是每一个新入队的引用实例都是作为头节点,已有的引用实例会作为后继节点 head = r; // 队列长度增加1 queueLength++; // Update r.queue *after* adding to list, to avoid race // with concurrent enqueued checks and fast-path poll(). // Volatiles ensure ordering. // 当前引用实例已经入队,那么它本身持有的引用队列实例置为ReferenceQueue.ENQUEUED r.queue = ENQUEUED; // 特殊处理FinalReference,VM进行计数 if (r instanceof FinalReference) { VM.addFinalRefCount(1); } // 唤醒所有等待的线程 lock.notifyAll(); returntrue; } }
// 引用队列的poll操作,此方法必须在加锁情况下调用 private Reference<? extends T> reallyPoll() { /* Must hold lock */ Reference<? extends T> r = head; if (r != null) { r.queue = NULL; // Update r.queue *before* removing from list, to avoid // race with concurrent enqueued checks and fast-path // poll(). Volatiles ensure ordering. @SuppressWarnings("unchecked") Reference<? extends T> rn = r.next; // Handle self-looped next as end of list designator. // 更新next节点为头节点,如果next节点为自身,说明已经走过一次出队,则返回null head = (rn == r) ? null : rn; // Self-loop next rather than setting to null, so if a // FinalReference it remains inactive. // 当前头节点变更为环状队列,考虑到FinalReference尚为inactive和避免重复出队的问题 r.next = r; // 队列长度减少1 queueLength--; // 特殊处理FinalReference,VM进行计数 if (r instanceof FinalReference) { VM.addFinalRefCount(-1); } return r; } returnnull; }
// 队列的公有poll操作,主要是加锁后调用reallyPoll public Reference<? extends T> poll() { if (head == null) returnnull; synchronized (lock) { return reallyPoll(); } } // 移除引用队列中的下一个引用元素,实际上也是依赖于reallyPoll的Object提供的阻塞机制 public Reference<? extends T> remove(long timeout) throws IllegalArgumentException, InterruptedException{ if (timeout < 0) { thrownew IllegalArgumentException("Negative timeout value"); } synchronized (lock) { Reference<? extends T> r = reallyPoll(); if (r != null) return r; long start = (timeout == 0) ? 0 : System.nanoTime(); for (;;) { lock.wait(timeout); r = reallyPoll(); if (r != null) return r; if (timeout != 0) { long end = System.nanoTime(); timeout -= (end - start) / 1000_000; if (timeout <= 0) returnnull; start = end; } } } } // remove,超时时间为0,实际上就是lock.wait(0)就是永久阻塞直至唤醒 public Reference<? extends T> remove() throws InterruptedException { return remove(0); }
// foreach voidforEach(Consumer<? super Reference<? extends T>> action){ for (Reference<? extends T> r = head; r != null;) { action.accept(r); @SuppressWarnings("unchecked") Reference<? extends T> rn = r.next; if (rn == r) { if (r.queue == ENQUEUED) { // still enqueued -> we reached end of chain r = null; } else { // already dequeued: r.queue == NULL; -> // restart from head when overtaken by queue poller(s) r = head; } } else { // next in chain r = rn; } } } }
finalclassFinalizerextendsFinalReference<Object> { /* Package-private; must be in same package as the Reference class */ // Finalizer关联的ReferenceQueue,其实Finalizer是一个特殊的Reference实现 privatestatic ReferenceQueue<Object> queue = new ReferenceQueue<>();
/** Head of doubly linked list of Finalizers awaiting finalization. */ // 等待finalization的所有Finalizer实例链表的头节点,这里称此链表为unfinalized链表 privatestatic Finalizer unfinalized = null;
// Clear stack slot containing this variable, to decrease // the chances of false retention with a conservative GC // 清空变量引用从而减少保守GC导致变量保留的可能性 finalizee = null; } } catch (Throwable x) { } // 执行完毕会做一次情况防止重复执行 super.clear(); }
/* Create a privileged secondary finalizer thread in the system thread * group for the given Runnable, and wait for it to complete. * * This method is used by runFinalization. * * It could have been implemented by offloading the work to the * regular finalizer thread and waiting for that thread to finish. * The advantage of creating a fresh thread, however, is that it insulates * invokers of that method from a stalled or deadlocked finalizer thread. */ // 这里其实不用畏惧注释太多,它只是一个候选方法,新建一个线程直接调用包裹在Runnable的runFinalization方法,主要是提供给主动调用的上层方法调用的 privatestaticvoidforkSecondaryFinalizer(final Runnable proc){ AccessController.doPrivileged( new PrivilegedAction<>() { public Void run(){ ThreadGroup tg = Thread.currentThread().getThreadGroup(); for (ThreadGroup tgn = tg; tgn != null; tg = tgn, tgn = tg.getParent()); Thread sft = new Thread(tg, proc, "Secondary finalizer", 0, false); sft.start(); try { sft.join(); } catch (InterruptedException x) { Thread.currentThread().interrupt(); } returnnull; }}); }
/* Called by Runtime.runFinalization() */ // 这个方法是给Runtime.runFinalization()委托调用的,其实就是主动取出queue的元素强制调用其finalize方法 staticvoidrunFinalization(){ if (VM.initLevel() == 0) { return; } forkSecondaryFinalizer(new Runnable() { privatevolatileboolean running; publicvoidrun(){ // in case of recursive call to run() if (running) return; final JavaLangAccess jla = SharedSecrets.getJavaLangAccess(); running = true; for (Finalizer f; (f = (Finalizer)queue.poll()) != null;) f.runFinalizer(jla); } }); } // 真正的Finalizer线程 privatestaticclassFinalizerThreadextendsThread{ privatevolatileboolean running; FinalizerThread(ThreadGroup g) { super(g, null, "Finalizer", 0, false); } publicvoidrun(){ // in case of recursive call to run() if (running) return;
// Finalizer thread starts before System.initializeSystemClass // is called. Wait until JavaLangAccess is available while (VM.initLevel() == 0) { // delay until VM completes initialization try { VM.awaitInitLevel(1); } catch (InterruptedException x) { // ignore and continue } } final JavaLangAccess jla = SharedSecrets.getJavaLangAccess(); running = true; // 注意这里是死循环 for (;;) { try { // 注意这里是调用`Reference#remove()`的永久阻塞版本,只有`Reference#enqueue()`被调用才会解除阻塞 // `Reference#remove()`解除阻塞说明元素已经完成入队,由ReferenceHandler线程完成 Finalizer f = (Finalizer)queue.remove(); // 实际上就是调用对象的finalize方法 f.runFinalizer(jla); } catch (InterruptedException x) { // ignore and continue } } } }
instanceOop InstanceKlass::register_finalizer(instanceOop i, TRAPS){ if (TraceFinalizerRegistration) { tty->print("Registered "); i->print_value_on(tty); tty->print_cr(" (" INTPTR_FORMAT ") as finalizable", p2i(i)); } instanceHandle h_i(THREAD, i); // Pass the handle as argument, JavaCalls::call expects oop as jobjects JavaValue result(T_VOID); JavaCallArguments args(h_i); // 这里Universe::finalizer_register_method()获取到的就是Finalizer#register方法句柄 methodHandle mh(THREAD, Universe::finalizer_register_method()); JavaCalls::call(&result, mh, &args, CHECK_NULL); return h_i(); }
最后调用的是javaCalls.cpp:
voidJavaCalls::call(JavaValue* result, const methodHandle& method, JavaCallArguments* args, TRAPS){ // Check if we need to wrap a potential OS exception handler around thread // This is used for e.g. Win32 structured exception handlers assert(THREAD->is_Java_thread(), "only JavaThreads can make JavaCalls"); // Need to wrap each and every time, since there might be native code down the // stack that has installed its own exception handlers os::os_exception_wrapper(call_helper, result, method, args, THREAD); }
StrongReference也就是强引用,它是使用最普遍的一种引用,java.lang.ref包下没有强引用对应的类型。一个比较明确的强引用定义就是:所有和GC Root之间存在引用链的对象都具备强引用。举个简单例子:形如Object o = new Object();在方法体中使用new关键字声明的对象一般就是强引用。如果一个对象具备强引用,垃圾回收器绝不会回收它。当内存空间不足,JVM宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会出现回收具有强引用的对象来解决内存不足的情况。当然,如果有共享的成员变量在方法退出之前置为null,相当于断绝成员变量和GC Root的引用链,在合适的时机是有利于GC后具备强引用的对象的回收,例如:
实际上,沙面的代码执行完毕只会输出”State runnable in action.State value = 11”,并没有输出”State runnable in action.State value = 22”,这是因为无法预测强引用对象被回收的时机。java.lang.ref.Cleaner主要是用于预防实现了AutoCloseable接口的实例忘记调用close()方法在对象被垃圾收集器回收的时候(内存回收)做一个兜底的清理工作,在JDK9之后,java.lang.ref.Cleaner主要是为了替代已经标识为过期的Object#finalize()方法。