Cleaner调用父类构造函数时,最终会进入到父类Reference
中的构造函数中:
referent:指向实际的引用对象,上面创建的是DirectByteBuffer
,所以这里指向的是DirectByteBuffer
。
queue:引用队列,指向Cleaner
中的引用队列dummyQueue
。
public class PhantomReference<T> extends Reference<T> {// ...public PhantomReference(T referent, ReferenceQueue<? super T> q) {super(referent, q); // 调用父类构造函数}}public abstract class Reference<T> {/* 引用对象 */private T referent;// 引用队列volatile ReferenceQueue<? super T> queue;Reference(T referent, ReferenceQueue<? super T> queue) {this.referent = referent;// 设置引用队列this.queue = (queue == null) ? ReferenceQueue.NULL : queue;}}

文章插图
启动ReferenceHandler线程
Reference
中有一个静态方法,里面创建了一个ReferenceHandler
并设置为守护线程,然后启动了该线程,并创建了JavaLangRefAccess
对象设置到SharedSecrets
中:public abstract class Reference<T> {static {ThreadGroup tg = Thread.currentThread().getThreadGroup();for (ThreadGroup tgn = tg;tgn != null;tg = tgn, tgn = tg.getParent());// 创建ReferenceHandlerThread handler = new ReferenceHandler(tg, "Reference Handler");// 设置优先级为最高handler.setPriority(Thread.MAX_PRIORITY);handler.setDaemon(true);handler.start();// 这里设置了JavaLangRefAccessSharedSecrets.setJavaLangRefAccess(new JavaLangRefAccess() {@Overridepublic boolean tryHandlePendingReference() {// 调用了tryHandlePendingreturn tryHandlePending(false);}});}}
ReferenceHandler
是Reference
的内部类,继承了Thread
,在run方法中开启了一个循环,不断的执行tryHandlePending
方法,处理Reference中
的pending
列表:public abstract class Reference<T> {private static class ReferenceHandler extends Thread {// ...ReferenceHandler(ThreadGroup g, String name) {super(g, name);}public void run() {while (true) {// 处理pending列表tryHandlePending(true);}}} }
Cleaner会启动一个优先级最高的守护线程,不断调用tryHandlePending来检测是否有需要回收的引用对象(还未进行真正的回收),然后进行处理 。处理pending列表垃圾回收器会将要回收的引用对象放在
Reference
的pending
变量中,从数据类型上可以看出pending
只是一个Reference
类型的对象,并不是一个list,如果有多个需要回收的对象,如何将它们全部放入pending
对象中?可以把pengding看做是一个链表的头结点,假如有引用对象被判定需要回收,如果pengding为空直接放入即可,如果不为空,将使用头插法将新的对象加入到链表中,也就是将新对象的discovered指向pending对象,然后将pending指向当前要回收的这个对象,这样就形成了一个链表,pending指向链表的头结点 。

文章插图
在pending链表中的引用对象处于pending状态 。
接下来看
tryHandlePending
方法的处理逻辑:- 如果pending不为空,表示有需要回收的对象,此时将pengding指向的对象放在临时变量
r
中,并判断是否是Cleaner类型,如果是将其强制转为Cleaner
,记录在临时变量c
中,接着更新pending的值为r的discovered,因为discovered中记录了下一个需要被回收的对象,pengding需要指向下一个需要被回收的对象;经验总结扩展阅读
- 旧事重提为什么要改名为朝花夕拾
- 德人易行是什么公司
- 单反相机的原理
- 豆芽怎么几天不发芽
- 卖瓷砖的利润怎么样
- 区什么工什么的成语
- 和三五有关的成语
- 如何评价迪士尼电影的宣传和营销
- 雨衣属于什么垃圾
- 粽叶是什么植物的叶子