Platform
OS: OS X EI Capitan 10.11.6 (15G31)
JAVA version: 1.8.0_45
概述
个人还是比较喜欢图形化的东西,所以这两天在看过Reference之后,就把它的概念图画了出来。
根据Reference这个类里面的注释,整个Reference的继承体系跟GC是紧密联系在一起的。当Reference对象被GC处理过,说明这个Reference所指向的对象已经被回收过了,那么这个Reference对象也应该做相应的处理;如果该Reference对象注册了ReferenceQueue,那么它就会被丢到相应的ReferenceQueue中做回收处理。
Main Idea
这里Reference世界跟GC的接口就是这个Reference.pending,这个每个JVM实例只有一个,用来接受GC的请求。Reference世界中在类加载后就会启动一个无限循环的线程Reference.ReferenceHandler,用来从Reference.pending上取下一个Reference对象,然后把该Reference对象放入它所关联的ReferenceQueue里面。
Reference对象到达自己的队列,谁来处理这些对象呢?那么就要看这些ReferenceQueue是谁来维护的,谁维护,谁处理?在源码中就是跟随着ReferenceQueue的remove方法,看看是谁调用了这个方法,就知道有多少服务方维护了多少ReferenceQueue。
举个例子,我在google的guava-16.0.1中找到了com.google.common.base.internal.Finalizer这个类,它就完成了上面的消费ReferenceQueue的功能。
写到这里,这让我想到了现在在互联网领域里面用的比较多的请求队列。GC相当于客户端,向服务器Reference发送了一个请求,然后服务端并没有同步的处理这些请求,而是放到了请求队列里做异步处理,每个服务端为了处理请求必须创建并维护自己的ReferenceQueue。
代码浅析
当我看源码时,看到了下面的注释。
/* When active: NULL
* pending: this
* Enqueued: next reference in queue (or this if last)
* Inactive: this
*/
@SuppressWarnings("rawtypes")
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
*/
transient private Reference<T> discovered; /* used by VM */
/* 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. The
* list uses the