一 概述


在JDK1.2之前,Java中的引用的定义是十分传统的:如果引用类型的变量中存储的数值代表的是另一块内存的起始地址,就称这块内存代表着一个引用(因此可以这样理解,所谓的引用其实就是一块保存了具体数据的内存的起始地址)。在这种定义之下,一个对象只有被引用和没有被引用两种状态。

实际上,我们更希望存在这样的一类对象:当内存空间还足够的时候,这些对象能够保留在内存空间中;如果当内存空间在进行了垃圾收集之后还是非常紧张,则可以抛弃这些对象。基于这种特性,可以满足很多系统的缓存功能的使用场景。

从JDK 1.2起,对引用概念进行了扩充,将引用分为强引用(Strong Reference)、软引用(Soft Reference)、弱引用(Weak Reference)、虚引用(Phantom Reference)及终引用(Final Reference)。其中强引用就是JDK 1.2之前的引用,日常代码中绝大多数引用都是强引用。而其它几种引用则是JDK 1.2中引入的,这些引用有着各自的特性及作用,例如软引用就代表了上述需求的“将对象在内存空闲时保留,不足时舍弃”的功能。这些引用概念存在着相应的类实现,Java其通过Java类与底层机制相结合的方式实现了这些概念,而重点是这些类又全都继承自同一个父类,也是本文真正的核心 —— Referecne(引用)类。

Referecne(引用)类是强引用之外的引用(下文简称特殊引用)概念的实质化产物,定义并实现了特殊引用的生命周期及运行流程。因为Referecne(引用)类的存在,特殊引用不再是一个虚幻的设想,而是实实在在的运行机制,也为软、弱等引用的实现提供了实质性的基础。Referecne(引用)类机制的运行流程如下:

  1. 由GC线程将活动状态且注册了引用队列的Referecne(引用)类对象加入待定列表中;
  2. 由“引用处理器”线程将Referecne(引用)类对象从待定列表迁移至其注册的引用队列中;
  3. 由用户线程从引用队列中取出Referecne(引用)类对象,由此判断所指对象已被GC回收,并执行自定义操作。

二 Referecne(引用)类源码及机制详解


Referecne(引用)类是所有引用类的父(超)类。

/*** 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.* 引用对象的抽象基类。该类定义了所有引用对象的通用操作。* 因为引用对象是与垃圾收集器密切合作实现的,所以不能直接对该类进行子类化。** @author Mark Reinhold* @Description: 引用类,是所有引用类的父类,定义了强引用之外引用概念。* @since 1.2*/
public abstract class Reference<T> {...
}

字段

referent(所指对象) —— Referecne(引用)类对象关联的具体对象,意味着该对象具有了特殊引用,会收到GC的特殊处理。

 ** @Description: 所指对象,即具体关注其引用关系的对象。*/
private T referent;         /* Treated specially by GC */

queue(引用队列) —— 专门与Referecne(引用)类配合使用的队列,如果Referecne(引用)类对象注册了引用队列(即queue(引用队列)字段不为null),则其会在所指对象被GC回收时加入引用队列,此时开发者就可以通过获取引用队列中Referecne(引用)类对象判断其对应的所指对象是否被GC回收,并同时可以在此时机执行一些自定义的操作。除此以外,queue(引用队列)字段还被用于与next(下个引用)字段相配合表示Referecne(引用)类对象的状态,这是一个未通过具体字段实现的概念。除此之外,该值还被用于判断当前Referecne(引用)类对象是否已被加入引用队列中。当Referecne(引用)类对象被加入/移除其注册的引用队列后,会将该字段值设置为“入队”引用队列/“空”引用队列,因此该字段可作为判断Referecne(引用)类对象是否出/入队的标志。

/*** @Description: 引用队列,如果引用队列存在,则所指对象被GC回收后,会将对应的引用对象存入到引用队列中。*/
volatile ReferenceQueue<? super T> queue;

next(下个引用) —— 当Referecne(引用)类对象位于引用队列时用于持有后继Referecne(引用)类对象的引用。除此以外,next(下个引用)字段还被用于与queue(引用队列)字段相配合表示Referecne(引用)类对象的状态,这是一个未通过具体字段实现的概念。

/*** When active:   NULL * pending:   this * Enqueued:   next reference in queue (or this if last) * Inactive:   this * 活动:null;* 待定:自身;* 入队:引用队列中后继引用对象的引用,如果当前引用对象是引用队列中的最后一个节点,则指向自身;* 怠惰:自身。*/
@SuppressWarnings("rawtypes")
volatile Reference next;

discovered(发现引用) —— 当Referecne(引用)类对象位于发现/待定列表时用于持有后继Referecne(引用)类对象的引用(如果是发现列表中的最后一个元素,值为自身。如果是待定列表中的最后一个元素,值为null)。发现列表是一个由GC负责维护的列表,目前还没有找到相关资料描述,但个人猜测可能与GC的可达性分析有关。当Referecne(引用)类对象为active(活动)状态是其值为发现列表中的后继Referecne(引用)类对象的引用,因此可知Referecne(引用)类对象被创建之时就被加入了发现列表。

/*** 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* 活动:由GC负责维护的发现列表中的后继引用对象的引用,如果当前引用对象是发现列表中的最后一个节点,则指向自身;* 待定:待定列表中的后继引用对象的引用,如果当前引用对象是待定列表中的最后一个节点,则为null;* 否则:null。*/
transient private Reference<T> discovered;  /* used by VM */

lock(锁) —— 该字段值用于访问待定列表时作为同步手段的锁对象使用。该字段是一个私有的静态变量,因此可知是一个类锁。

/*** Object used to synchronize with the garbage collector.  The collector* must acquire this lock at the beginning of each collection cycle.  It is* therefore critical that any code holding this lock complete as quickly* as possible, allocate no new objects, and avoid calling user code.** @Description: 锁类*/
static private class Lock {}/*** @Description: 静态类型的锁对象,用于加类锁*/
private static Lock lock = new Lock();

pending(待定引用) —— 待定列表的头Referecne(引用)类对象。待定列表不是一个真正意义上列表对象,而是一个通过链接组成的概念列表,而pending(待定引用)字段便表示其头Referecne(引用)类对象,因此可知只要获得了头Referecne(引用)类对象就相当于获得了整个待定列表。pending(待定引用)字段是一个私有的静态变量,因此可知整个JVM中就只有一个待定列表,且该字段由GC负责赋值。

待定列表用于保存处于active(活动)状态且注册了引用队列的Referecne(引用)类对象。Referecne(引用)类对象一开始会存在于发现列表中,GC会将其中需要执行Referecne(引用)类机制的对象挑选出来置入待定列表中,以供“引用处理器”线程进行处理。

/*** 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 discovered field to link its elements.* 等待加入引用队列的引用对象。由收集器负责将引用对象加入该队列中,直到引用处理器线程将之移除。* 该列表受上述锁对象保护(即类锁)。该列表通过"discovered"字段链接其的元素。*/
private static Reference<Object> pending = null;

state(状态) —— Referecne(引用)类存在状态的概念,但这个概念并没有采用类似于state的字段直接实现,而是通过组合判断queue(引用队列)字段及next(下个引用)字段在不同状态下的值来表现的。相关的状态及源码注释如下:

active(活动):active(活动)状态是Referecne(引用)类对象的初始状态,这个状态下的Referecne(引用)类对象会受到GC的“特殊照顾”。当对象被判定为可回收后,如果该Referecne(引用)类对象注册了引用队列,GC会将之加入到待定队列中(加入引用队列的前置操作),相当于将状态修改为了pending(待定)。而如果Referecne(引用)类对象没有注册引用队列的话则会直接将其状态变为inactive(怠惰)。当Referecne(引用)类对象的状态为active(活动)时,queue(引用队列)字段及next(下个引用)字段的值如下:
        queue(引用队列):自注册的引用队列对象或默认的"空"引用队列对象(如果为注册引用队列,会赋予一个默认的"空"引用队列对象表示未注册);
        next(下个引用):null(active(活动)是唯一一个“next”字段为null的状态,因此可以直接通过判断“next”字段是否为null来判断其是否为active(活动)状态)。

pending(待定):当Referecne(引用)类对象被GC加入待定列表时,即表示其状态变为了pending(待定)状态,这个状态下的Referecne(引用)类对象正等待着被“引用处理器”线程加入到引用队列中。由于加入待定列表是将Referecne(引用)类对象加入到引用队列的前置步骤,因此可知只有注册了引用队列的Referecne(引用)类对象才能够转变为这个状态。当Referecne(引用)类对象的状态为pending(待定)时,queue(引用队列)字段及next(下个引用)字段的值如下:
        queue(引用队列):自注册的引用队列对象(pending(待定)状态下的Referecne(引用)类对象必然注册了引用队列);
        next(下个引用):this(即当前Referecne(引用)类对象,是专门为了区分状态而赋的值)。

enqueue(入队):当Referecne(引用)类对象被“引用处理器”线程加入自注册的引用队列时,即表示其状态变为了enqueue(入队)状态,这个状态下的Referecne(引用)类对象正等待着被用户线程从引用队列中取出并执行相应的操作(开发者自定义)。当enqueue(入队)状态下的Referecne(引用)类对象被用户线程从引用队列移除时,意味着其变为了inactive(怠惰)状态,同时也意味着一个Referecne(引用)类对象可能永远都不会变为inactive(怠惰)…如果其永远都没有出队的话。当Referecne(引用)类对象的状态为enqueue(入队)时,queue(引用队列)字段及next(下个引用)字段的值如下:
        queue(引用队列):“入队”引用队列对象(一个与“空”引用队列对象相同的预定值,表示当前Referecne(引用)类对象已经加入的引用队列,可用做Referecne(引用)类对象是否入队的判断条件);
        next(下个引用):引用队列中后继Referecne(引用)类对象的引用。

inactive(怠惰):Referecne(引用)类对象转变为inactive(怠惰)状态有两种方式:一是因为没有注册引用队列而被GC设置;二是其从引用队列中出队时被用户线程设置。一个状态已经被转变为inactive(怠惰)的Referecne(引用)类对象意味着其已经没有什么事情可以做了,处于生命周期的尾声,存在的唯一意义就是等待被GC回收。当Referecne(引用)类对象的状态为inactive(怠惰)时,queue(引用队列)字段及next(下个引用)字段的值如下:
        queue(引用队列):"空"引用队列对象("空"引用队列对象即是Referecne(引用)类对象未注册引用队列的默认值,也是其从引用队列中出队时会被赋予的终结值,因此"空"引用队列对象有着双重含义);
        next(下个引用):this(即当前Referecne(引用)类对象,是专门为了区分状态而赋的值)。

/*** A Reference instance is in one of four possible internal states:* 引用对象可能处于以下四种内部状态之一:* <p>* Active: Subject to special treatment by the garbage collector.  Some* time after the collector detects that the reachability of the* referent has changed to the appropriate state, it changes the* instance's state to either Pending or Inactive, depending upon* whether or not the instance was registered with a queue when it was* created.  In the former case it also adds the instance to the* pending-Reference list.  Newly-created instances are Active.* 活动:受到GC的特殊处理(引用对象本身就区别于常规对象,其是专用于实现与GC密切相关的引用关系的,这代表GC的运行对其存在依赖* 关系,因此对其的处理自然不可能与常规对象等同。GC对引用对象的特殊处理主要有两点:一是可达性分析,如果在可达性分析的过程中追* 踪到了引用对象,那么对其所指对象的回收判断必然会产生影响。例如一个软引用对象可能会使得GC对所指对象的存活时间进行计算,以判* 断其保留或回收。二是对引用对象的后续处理,例如将之加入到引用队列中。但无论是哪一种都有一个前提,即引用对象必须是"活动"状态。* 因为对于前者,只有"活动"状态才表示其所指对象未被判定为可回收。而对于后者,也只有"活动"状态才表示其自身还未被告知应执行加入引用* 队列的流程。因此对于GC而言,只有"活动"状态的引用对象才有意义,否则其也就是个可达性分析中的中转站或终点而已。)。在GC检测到* 所指对象的可达性已更改为适当状态(即可回收)的一段时间后,它会将引用对象的状态更改为"待定"或"怠惰",这取决于该引用对象在创建时* 是否注册引用队列。在前一种情况下(待定),GC还会将引用对象添加到待定列表中。新创建的实例是"活动"的。* <p>* Pending: An element of the pending-Reference list, waiting to be* enqueued by the Reference-handler thread.  Unregistered instances* are never in this state.* 待定:一个待定列表的元素(即当前引用对象已经加入待定列表),* 正等待着被"引用处理器"线程入队(即加入引用队列)。* 没有注册引用队列的引用对象永远不会处于这个状态。* <p>* Enqueued: An element of the queue with which the instance was* registered when it was created.  When an instance is removed from* its ReferenceQueue, it is made Inactive.  Unregistered instances are* never in this state.* 入队:一个引用对象创建时注册的引用队列的元素(即当前对象已被加入引用队列)。* 当引用对象从它的引用队列中删除时,它会变为"怠惰"。* 没有注册引用队列的引用对象永远不会处于这个状态。* <p>* Inactive: Nothing more to do.  Once an instance becomes Inactive its* state will never change again.* 怠惰:没有什么可做的。一旦一个引用对象变为"怠惰"状态将永远不会再改变。* "怠惰"状态的改变有两种情况:* 未注册引用队列:活动(初始状态) - > 怠惰(最终状态 —— 未加入引用队列)* 已注册引用队列:活动(初始状态) -> 待定(已加入待定列表) -> 入队(已加入引用队列) -> (最终状态 —— 已退出引用队列)* <p>* The state is encoded in the queue and next fields as follows:* 状态在引用队列及"next"字段中的编码如下:* Reference类并没定义具体的状态字段及状态值,因此其具体的判断通过"queue"及"next"两个字段组合实现。* <p>* Active: queue = ReferenceQueue with which instance is registered, or* ReferenceQueue.NULL if it was not registered with a queue; next =* null.* 活动:当引用对象处于"活动"状态时,"queue"字段为引用对象注册的引用队列或默认"空"引用队列(如果没有注册引用队列会默认给予一个* 空队列)。而"next"字段为null。"next"字段是用于记录引用对象在引用队列中的后继引用对象的,一个没有注册引用队列的引用对象自然不* 会有后继引用对象。* <p>* Pending: queue = ReferenceQueue with which instance is registered;* next = this* 待定:当引用对象处于"待定"状态时,"queue"字段为引用对象注册的引用队列(只有注册了引用队列的引用对象才能变为"待定"状态)。而* "next"字段为当前引用对象,用于GC作为状态判断的标志。此处"next"字段的修改是由GC完成的,可以看到"next"是一个私有字段,并且不* 存在set()方法,因此其的赋值应该是通过反射机制实现的。* <p>* Enqueued: queue = ReferenceQueue.ENQUEUED; next = Following instance* in queue, or this if at end of list.* 入队:当引用对象处于"入队"状态时,"queue"字段为"入队"引用队列,这个队列与"空"引用队列一样都是一个预定值,一旦引用对象被加入到* 其注册的引用队列中后,"queue"字段就会被替换为"入队"引用队列表示其已经成功入队。而"next"字段为其在引用队列中的后继引用对象或其* 本身(如果是第一个入队的引用对象的话)。* <p>* 怠惰:当引用对象处于"怠惰"状态时,"queue"字段为"空"引用队列。"空"引用队列表示其未注册引用队列或已经从注册的引用队列中出队。而* "next"字段为当前引用对象。* Inactive: queue = ReferenceQueue.NULL; next = this.* <p>* With this scheme the collector need only examine the next field in order* to determine whether a Reference instance requires special treatment: If* the next field is null then the instance is active; if it is non-null,* then the collector should treat the instance normally.* 根据方案GC只需要检查"next"字段,以确定引用对象是否需要特殊处理:如果"next"字段为null则表示引用对象的状态为"活动"(表示需要进行* 特殊处理,即将引用对象加入到引用队列中);如果"next"字段不为null,则GC应该正常处理。* <p>* To ensure that a concurrent collector can discover active Reference* objects without interfering with application threads that may apply* the enqueue() method to those objects, collectors should link* discovered objects through the discovered field. The discovered* field is also used for linking Reference objects in the pending list.* 为了确保并发收集器能够发现"活动"状态的引用对象而不会干扰可能对这些对象应用enqueue()方法的应用程序线程(即引用处理器线程),收* 集器应该通过"discovered"字段链接已发现的对象。"discovered"字段还用于链接待定列表中的引用对象。*/

静态块

在Referecne(引用)类的静态块中创建了一条引用处理器线程。该线程是Referecne(引用)类的内部类ReferenceHandler(引用处理器)类的实例,专用于执行Referecne(引用)机制,因此可知整个Referecne(引用)机制都是通过这一条线程来执行的。该线程是一条守护线程,优先级被设置为了10(最高),目的是尽可能多的获取CPU资源。

static {// 获取当前线程所在的线程组。ThreadGroup tg = Thread.currentThread().getThreadGroup();for (ThreadGroup tgn = tg; tgn != null; tg = tgn, tgn = tg.getParent());// 实例化一个引用处理线程,该线程是一个守护线程,并且是最高的优先级。该线程专用于将等待列表中的引用对象添加到引用队列中。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() {@Overridepublic boolean tryHandlePendingReference() {return tryHandlePending(false);}});
}

构造方法

Reference(T referent)/Reference(T referent, ReferenceQueue<? super T> queue) —— Referecne(引用)类有两个构造方法,对应着两种仅有的使用场景(注册/不注册引用队列)。无论是Referecne(引用)类还是其子类,所指对象是创建对象时必须指定的,毕竟如果连特殊引用所属的对象都没有的话,Referecne(引用)类对象还有什么意义呢?两个方法的访问权限都是DEFAULT,因此可知开发者是无法直接通过new关键字创建其对象的。

Reference(T referent) {this(referent, null);
}Reference(T referent, ReferenceQueue<? super T> queue) {this.referent = referent;this.queue = (queue == null) ? ReferenceQueue.NULL : queue;
}

方法

public T get() —— 获取 —— 该方法用于获取Referecne(引用)类对象对应的所指对象,所指对象不存在时会返回null,例如所指对象已经被GC回收。

/*** 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 <code>null</code>.** @return The object to which this reference refers, or* <code>null</code> if this reference object has been cleared*/
public T get() {return this.referent;
}

public void clear() —— 清除 —— 该方法会将Referecne(引用)类对象对应的所指对象清除,即断开两者的引用关系,并且也不会将Referecne(引用)类对象加入到引用队列中。该方法是专门给Java代码使用的,GC会直接通过底层断开两者的引用关系,而不会调用此方法。

/*** Clears this reference object.  Invoking this method will not cause this* object to be enqueued.** <p> This method is invoked only by Java code; when the garbage collector* clears references it does so directly, without invoking this method.*/
public void clear() {this.referent = null;
}

public boolean isEnqueued() —— 是否入队(false:否,true:是) —— 判断当前Referecne(引用)类对象是否已加入引用队列。Referecne(引用)类对象加入引用队列时会将queue(引用队列)字段的值设置为“入队”引用队列对象,因此判断Referecne(引用)类对象是否加入引用队列无需遍历引用队列,直接判断queue(引用队列)字段的值是否是“入队”引用队列对象即可。

/*** Tells whether or not this reference object has been enqueued, either by* the program or by the garbage collector.  If this reference object was* not registered with a queue when it was created, then this method will* always return <code>false</code>.** @return <code>true</code> if and only if this reference object has* been enqueued*/
public boolean isEnqueued() {return (this.queue == ReferenceQueue.ENQUEUED);
}

public boolean enqueue() —— 入队(false:失败,true:成功) —— 将当前Referecne(引用)类对象加入引用队列,底层调用引用队列的enqueue()方法实现。该方法是专门给Java代码使用的,“引用处理器”线程会直接调用引用队列的enqueue()方法将Referecne(引用)类对象加入引用队列。

/*** Adds this reference object to the queue with which it is registered,* if any.** <p> This method is invoked only by Java code; when the garbage collector* enqueues references it does so directly, without invoking this method.** @return <code>true</code> if this reference object was successfully* enqueued; <code>false</code> if it was already enqueued or if* it was not registered with a queue when it was created*/
public boolean enqueue() {return this.queue.enqueue(this);
}

static boolean tryHandlePending(boolean waitForNotify) —— 尝试处理待定列表(false:失败,true:成功) —— 该方法实现了Referecne(引用)类对象的运行流程,是Referecne(引用)机制的核心内容,因此需要重点学习。该方法的主要内容是将Referecne(引用)类对象从待定列表迁移至引用队列中,在此过程中存在一个特殊判断:即如果从Referecne(引用)类对象是其子孙类Cleaner(清洁工)类(该类是Referecne(引用)类的直接子类PhantomReferecne(虚引用)类的直接子类,在设计上用于对资源进行回收)的对象,则只会执行其自定义操作,而不会将之加入引用队列中。

/*** Try handle pending {@link Reference} if there is one.<p>* Return {@code true} as a hint that there might be another* {@link Reference} pending or {@code false} when there are no more pending* {@link Reference}s at the moment and the program can do some other* useful work instead of looping.** @param waitForNotify if {@code true} and there was no pending*                      {@link Reference}, wait until notified from VM*                      or interrupted; if {@code false}, return immediately*                      when there is no pending {@link Reference}.* @return {@code true} if there was a {@link Reference} pending and it* was processed, or we waited for notification and either got it* or thread was interrupted before being notified;* {@code false} otherwise.*/
static boolean tryHandlePending(boolean waitForNotify) {Reference<Object> r;Cleaner c;try {// 在类锁的保护下执行,因此是线程安全的。synchronized (lock) {if (pending != null) {// 如果待定引用不为null,说明已经有引用对象被GC加入到了待定列表中,获取待定引用(快照)。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//     设置待定引用为待定引用(快照)的发现引用,设置待定引用(快照)的发现引用为null。该操作的本质实际上就是待定列表的移除// 头引用对象并解除其与待定列表关系的过程。pending = r.discovered;r.discovered = null;} else {// The waiting on the lock may cause an OutOfMemoryError// because it may try to allocate exception objects.//     如果待定引用为null,则说明还没有引用对象被GC纳入等待列表中。如果waitForNotify为true,则将当前线程挂起,直至被唤醒或中// 断,目的是等待待定引用的到来。if (waitForNotify) {lock.wait();}// retry if waitedreturn 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...// 放弃当前的CPU资源,给其他线程一些时间释放一些引用。Thread.yield();// retryreturn true;} catch (InterruptedException x) {// retryreturn true;}// Fast path for cleaners// 如果待定引用(快照)是清洁工对象,则直接清理,即完成相关的处理后返回成功。待定引用(快照)不会被加入到引用队列中。if (c != null) {c.clean();return true;}// 获取待定引用(快照)的引用队列,并判断引用队列是否合法,即是否是一个真正的引用队列,如果是则直接将引用对象入队。ReferenceQueue<? super Object> q = r.queue;if (q != ReferenceQueue.NULL) q.enqueue(r);return true;
}

三 ReferenceHandler(引用处理器)类源码及机制详解


ReferenceHandler(引用处理器)类是Referecne(引用)类的一个静态内部类,继承自Thread(线程)类,因此可知该类的实例是一个线程。该类只有一个实例,也就是上文已经提及的“引用处理器”线程,该线程是拥有最高优先级的守护线程,专用于执行Referecne(引用)机制。

/*** High-priority thread to enqueue pending References** @Description: 引用处理器类,该类继承于线程类,因此其就是一个线程。*/
private static class ReferenceHandler extends Thread {...
}

静态块

预加载了两个所需的类…具体效果不是很清楚。

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.// 预加载InterruptedException与Cleaner两个类。ensureClassInitialized(InterruptedException.class);ensureClassInitialized(Cleaner.class);
}/*** @Description: 确保类初始化*/
private static void ensureClassInitialized(Class<?> clazz) {try {//     加载一个指定的类,即完成加载 - > 校验 - > 准备 - > 解析 - > 初始化。在第二个参数中传入了true,因此会执行类加载操作中的初始化操作,// 即执行指定类的静态代码块。Class.forName(clazz.getName(), true, clazz.getClassLoader());} catch (ClassNotFoundException e) {throw (Error) new NoClassDefFoundError(e.getMessage()).initCause(e);}
}

构造方法

ReferenceHandler(ThreadGroup g, String name) —— 调用父类Thread(线程)类的构造方法。

/*** @Description: 构造方法*/
ReferenceHandler(ThreadGroup g, String name) {super(g, name);
}

方法

public void run() —— 执行 —— 无限调用tryHandlePending()方法对待定列表中的Referecne(引用)类对象进行处理(加入引用队列中)。

/*** @Description: 执行*/
@Override
public void run() {// 死循环,这表示一旦开始就会永远运行,直至程序结束。while (true) {// 将待定状态的引用对象加入引用队列中。tryHandlePending(true);}
}

四 相关系列


  • 《Java ~ Reference》
  • 《Java ~ Reference ~ ReferenceQueue》
  • 《Java ~ Reference ~ SoftReference》
  • 《Java ~ Reference ~ WeakReference》
  • 《Java ~ Reference ~ PhantomReference/Cleaner》
  • 《Java ~ Reference ~ FinalReference/Finalizer》

Java ~ Reference相关推荐

  1. java Reference

    java reference Reference Java世界泰山北斗级大作<Thinking In Java>切入Java就提出"Everything is Object&qu ...

  2. 【JAVA Reference】Finalizer 剖析 (六)

    我的原则:先会用再说,内部慢慢来. 学以致用,根据场景学源码 文章目录 一.前言 二.架构 2.1 代码架构 2.2 UML流程图 三.思考 Finalizer Vs Cleaner 放一起 3.1 ...

  3. Java ~ Reference【总结】

    前言 文章 相关系列:<Java ~ Reference[目录]>(持续更新) 相关系列:<Java ~ Reference[源码]>(学习过程/多有漏误/仅作参考/不再更新) ...

  4. Java ~ Reference ~ PhantomReference【源码】

    前言 文章 相关系列:<Java ~ Reference[目录]>(持续更新) 相关系列:<Java ~ Reference ~ PhantomReference[源码]>(学 ...

  5. What Influences Method Call Performance in Java?--reference

    reference from:https://www.voxxed.com/blog/2015/02/too-fast-too-megamorphic-what-influences-method-c ...

  6. java reference详解_Java Reference详解

    Reference是java中的引用类,它用来给普通对像进行包装,从而在JVM在GC时,按照引用类型的不同,在回收时采用不同的逻辑.先来看下这个类的继承体系: image.png 在进行对这些子类进行 ...

  7. java reference 传引用_Java的引用(reference)---Roni

    摘自<Java面向对象编程>一书,作者:孙卫琴 来源:www.javathinker.org 在JDK1.2以前的版本中,当一个对象不被任何变量引用,那么程序就无法再使用这个对象.也就是说 ...

  8. java什么是reference_理解java reference

    Java世界泰山北斗级大作<Thinking In Java>切入Java就提出"Everything is Object".在Java这个充满Object的世界中,r ...

  9. java reference详解_你不可不知的Java引用类型之——Reference源码解析

    定义 Reference是所有引用类型的父类,定义了引用的公共行为和操作. reference指代引用对象本身,referent指代reference引用的对象,下文介绍会以reference,ref ...

最新文章

  1. [PHP] JQuery+Layer实现添加删除自定义标签代码
  2. 第31届NIPS正式开幕,3240篇提交论文创历史新高,公布3篇最佳论文
  3. 中国行政区划信息JS库china-location
  4. ParaEngine 一个同事的公司的开源引擎
  5. 一段字符串修改某一个位置的值
  6. 怎么用计算机搜索文件,Win7系统如何使用内置搜索功能筛选文件名与内容
  7. luogu P1015 回文数
  8. 9月29日 胶囊网络
  9. Windows 7如何无线上网和宽带上网
  10. 塔防java_塔防游戏--java游戏
  11. MATLAB数字图像小系统
  12. 什么是嵌入式操作系统 常见的嵌入式系统有哪些
  13. 上任第十年,库克功与过
  14. Neo4j 第二篇:图形数据库
  15. 新安装的福昕阅读器总是弹出“文件安全进程防护”
  16. 华为机器学习服务语音识别功能,让应用绘“声”绘色
  17. 再看同义变换在百度搜索广告中的应用总结
  18. 5分钟爬虫教程:如何用 Python 爬一些微电影?
  19. python笔记 - EasyGui的使用
  20. python倾向匹配得分_在SPSS软件中实现1:1倾向性评分匹配(PSM)分析

热门文章

  1. 计算机信息安全与防范任务书,2013-14信息安全综合实践任务书.pdf
  2. python数据分析比较好的书籍_python数据分析比较好的书籍推荐|陇川制作项目盈利能力分析...
  3. The event in requested index is outdated and cleared (the requested history has been cleared ) 问题和修复
  4. python3函数参数(必选参数、默认参数、关键字参数、可变参数)
  5. Sigmoid函数的理解
  6. 15.Set里的元素是不能重复的,那么用什么方法来区分重复与否呢? 是用==还是equals()? 它们有何区别?
  7. 「引流方法」微商如何获得精准引流的八大方法
  8. Android measure方法详解
  9. 转:世上最愚蠢的行为,就是讲道理
  10. P2467 [SDOI2010]地精部落(dp n个数此起彼伏)