Java ~ Reference ~ PhantomReference【源码】

前言


 文章

  • 相关系列:《Java ~ Reference【目录】》(持续更新)
  • 相关系列:《Java ~ Reference ~ PhantomReference【源码】》(学习过程/多有漏误/仅作参考/不再更新)
  • 相关系列:《Java ~ Reference ~ PhantomReference【总结】》(学习总结/最新最准/持续更新)
  • 相关系列:《Java ~ Reference ~ PhantomReference【问题】》(学习解答/持续更新)
  • 参考文献:《Java原生内存管理(native memory management)(4)-PhantomReference和WeakReference对比》
  • 参考文献:《虚引用所指向的对象到底什么时候被回收?》
  • 涉及内容:《Java ~ Reference ~ Cleaner【总结】》

一 PhantomReference(虚引用)类概述


    PhantomReference(虚引用)类是Reference(引用)类的四大子类之一,只被PhantomReference(虚引用)类对象持有的对象被称为虚可达(phantom reachable)对象。在Java中关于虚引用的定义是:虚引用等价于没有引用,其无法对对象的生命周期产生任何影响,即对象的诞生、初始化、使用及回收完全与虚引用无关。这段描述与弱引用完全相同,以至于令人怀疑是不是复制黏贴的…但实际上两者确实高度相似。

    PhantomReference(虚引用)类被用于跟踪对象被垃圾回收的活动,通俗的讲就是判断对象是否已经被GC回收。当GC发生时,如果发现某个该回收的对象存在虚引用,则会将该对象的相关PhantomReference(虚引用)类对象加入到引用队列中,而当我们从引用队列中获取到了出队的PhantomReference(虚引用)类对象,就可以判定其所指对象已经被GC回收了(这种说法其实并不正确,但近似可以这样理解,具体会在下文讲述)。

    PhantomReference(虚引用)类有两个特点:一是必须与引用队列搭配使用,这与其本身的作用相关;二是其get()方法无法获取所指对象,即使其没有被GC回收。如此设计的目的是为了凸显其作用,PhantomReference(虚引用)类的设计者(Mark Reinhold:马克·莱因霍尔德)目的非常明显,他只希望PhantomReference(虚引用)类被用于其仅有的设计作用上(跟踪对象被垃圾回收的活动),除此以外没有任何使用它的理由。

    PhantomReference(虚引用)类可作为finalize()方法的替代方案。由于PhantomReference(虚引用)类对象的存在,开发者能够知晓其所指对象是否已被GC回收,也因此可在所指对象被GC回收时执行自定义操作,这有点类似于方法finalize()的作用,因此PhantomReference(虚引用)类也被提倡作为finalize()方法的替代方案,毕竟finalize()方法本身存在着诸多缺陷…实际上WeakReference(弱引用)类同样可作为finalize()方法的替代方案,但其自身特性决定了其必然可用于功能更加强大的场景。而PhantomReference(虚引用)类很专一…除了这事儿我啥都干不了,甚至还专门为此拓展了一个子类Cleaner(清洁工)类

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


 类

    PhantomReference(虚引用)类继承自Reference(引用)类。

/**
 * Phantom reference objects, which are enqueued after the collector
 * determines that their referents may otherwise be reclaimed.  Phantom
 * references are most often used for scheduling pre-mortem cleanup actions in
 * a more flexible way than is possible with the Java finalization mechanism.
 * 虚引用对象,在收集器确定它们的引用对象可能以其他方式被回收后进入队列。
 * 虚引用最常用于以一种比Java终结机制更灵活的方式调度死前清理操作。
 * 

* If the garbage collector determines at a certain point in time that the * referent of a phantom reference is phantom reachable, then at that * time or at some later time it will enqueue the reference. * 如果垃圾回收器在某个时间点确定一个虚引用的引用是虚可达的,那么在那个时间点或稍后的某个时间点,它将对该引用进行入队。 *

* In order to ensure that a reclaimable object remains so, the referent of * a phantom reference may not be retrieved: The get method of a * phantom reference always returns null. * 为了确保可回收对象保持原样,虚引用的引用可能不会被检索:虚引用的get()方法总是返回null。 *

* Unlike soft and weak references, phantom references are not * automatically cleared by the garbage collector as they are enqueued. An * object that is reachable via phantom references will remain so until all * such references are cleared or themselves become unreachable. * 与软引用和弱引用不同,虚引用在进入队列时不会被垃圾收集器自动清除。 * 通过虚引用可访问的对象将保持这种状态,直到所有此类引用被清除或其本身变得不可访问。 * * @author Mark Reinhold * @since 1.2 */ public class PhantomReference<T> extends Reference<T> { ... }

 构造方法

    public PhantomReference(T referent, ReferenceQueue q) —— PhantomReference(虚引用)类只有一个构造函数,可知其必须搭配引用队列使用。

/**
 * Creates a new phantom reference that refers to the given object and
 * is registered with the given queue.
 *
 * 

It is possible to create a phantom reference with a null * queue, but such a reference is completely useless: Its get * method will always return null and, since it does not have a queue, it * will never be enqueued. * * @param referent the object the new phantom reference will refer to * @param q the queue with which the reference is to be registered, * or null if registration is not required */ public PhantomReference(T referent, ReferenceQueue<? super T> q) { // 所指对象及引用队列。虚引用类不存在其它构造函数,这意味着虚引用类必须搭配引用队列使用。 super(referent, q); }

 方法

    public T get() —— 获取 —— PhantomReference(虚引用)类的get()方法经过重写后会永远返回null。这是为了防止通过get()方法获取到对象后重新与GC Roots建立引用关系而使其复活。

/**
 * Returns this reference object's referent.  Because the referent of a
 * phantom reference is always inaccessible, this method always returns
 * null.
 *
 * @return null
 */
@Override
public T get() {
    // 永远返回null。
    return null;
}

你可能感兴趣的:(Java,jvm,Reference,Java)