《Java源码分析》:ReferenceQueue、Reference及其子类

本文详细介绍了Java中的`ReferenceQueue`、`Reference`类及其子类`SoftReference`、`WeakReference`和`PhantomReference`。`ReferenceQueue`是一个与垃圾回收器交互的队列,当引用对象的可达性改变时,会被添加到队列中。`Reference`类有4种状态:Active、Pending、Enqueued和Inactive。四种引用类型在内存管理中扮演不同角色,软引用在内存不足时才回收,弱引用在GC发现时回收,虚引用用于预回收阶段的清理动作。文章还探讨了引用状态转换、内部属性以及引用类在实际应用中的用法。
摘要由CSDN通过智能技术生成

《Java源码分析》:ReferenceQueue、Reference及其子类

在看完WeakHashMap源码之后,看了有关于讲解WeakHashMap的些许博客,发现了几个比较有意思的类:Reference、Reference子类(SoftReference、WeakReference、PhantomReference)以及ReferenceQueue。

以前自己只是知道这些类的存在,在看WeakHashMap源码之前并不知道他们的用途,因此,借此机会自己就想对这几个类了解下,查了网上相关资料、看了源码和相关API文档,都没能完全的理解这些类以及这些类和垃圾回收之间的交互,只是有一个小小的认识。下面就来一一进行说明,若有错误,请指出并谅解。

1、ReferenceQueue类

由于Reference类中有关于ReferenceQueue的引用,因此,先对ReferenceQueue进行介绍。

源码中对该类的说明摘入如下:

Reference queues, to which registered reference objects are appended by the
garbage collector after the appropriate reachability changes are detected.

中文意思为:Reference queues,在适当的时候检测到对象的可达性发生改变后,垃圾回收器就将已注册的引用对象添加到此队列中。

此类中的方法比较少,只有:enqueue(Reference

    //出队标识
    static ReferenceQueue<Object> NULL = new Null<>();
    //出队标识
    static ReferenceQueue<Object> ENQUEUED = new Null<>();
    //锁对象
    static private class Lock { };
    private Lock lock = new Lock();
    //链表的头结点
    private volatile Reference<? extends T> head = null;
    //队列的大小
    private long queueLength = 0;

    boolean enqueue(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<?> queue = r.queue;
            if ((queue == NULL) || (queue == ENQUEUED)) {
                return false;
            }
            assert queue == this;
            r.queue = ENQUEUED;//入队标识
            r.next = (head == null) ? r : head;
            head = r;
            queueLength++;
            if (r instanceof FinalReference) {
                sun.misc.VM.addFinalRefCount(1);
            }
            lock.notifyAll();
            return true;
        }
    }

2、poll()方法

实现思路也相当简单,就是判断队列中是否为空,如果不为空,则取出链表中head位置的元素即可,出队的Reference对象要加上出队标识NULL。

源码如下:

    public Reference<? extends T> poll() {
        if (head == null)
            return null;
        synchronized (lock) {
            return reallyPoll();
        }
    }

    @SuppressWarnings("unchecked")
    private Reference<? extends T> reallyPoll() {       /* Must hold lock */
        Reference<? extends T> r = head;
        if (r != null) {
            head = (r.next == r) ?
                null :
                r.next; // Unchecked due to the next field having a raw type in Reference
            r.queue = NULL;//出队标识
            r.next = r;//出队的Reference对象的next指向自己
            queueLength--;
            if (r instanceof FinalReference) {
                sun.misc.VM.addFinalRefCount(-1);
            }
            return r;
        }
        return null;
    }

remove方法这里就不再介绍,以上就是关于ReferenceQueue的一个简单的介绍。

2.Reference类

2.1、介绍

在Reference类源码的开头对此类有一个说明,摘入如下:

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.

比较好理解,中文翻译为:这是引用对象的抽象基类,这个类中定义了所有引用对象的常用操作。由于引用对象是通过与垃圾回收器密切合作来实现的,因此,不能直接为此类创建子类。

以上就是源码中对此类的一个说明,我们可能获得到的有用信息为:Reference类是基类且和GC是密切相关的。

2.2、Reference类的4中状态

在源码中,我们可以了解到,Reference有4种状态:

1)、Active

源码中对Active状态说明如下:

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.

翻译为:Active状态的Reference会受到GC的特别关注,当GC察觉到引用的可达性变化为其它的状态之后,它的状态将变化为Pending或Inactive,到底转化为Pending状态还是Inactive状态取决于此Reference对象创建时是否注册了queue.如果注册了queue,则将添加此实例到pending-Reference list中。 新创建的Reference实例的状态是Active。

每当我自己翻译的时候,都感觉翻译技术书籍的人真心不容易,很多东西我们自己知道是什么意思,但是当翻译过来的时候总是感觉没有描述清楚

2)、Pending

源码中对此状态给出的解释为:

Pending: An element of the pending-Reference list, waiting to be
enqueued by the Reference-handler thread. Unregistered instances
are never in this state.

翻译为:在pending-Reference list中等待着被Reference-handler 线程入队列queue中的元素就处于这个状态。没有注册queue的实例是永远不可能到达这一状态。

3)、Enqueued

源码中对此状态给出的解释为:

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.

翻译为:当实例被移动到ReferenceQueue中时,Reference的状态为Inactive。没有注册ReferenceQueue的不可能到达这一状态的。

4)、Inactive

源码中对此状态给出的解释为:

Inactive: Nothing more to do. Once an instance becomes Inactive its
state will never change again.

翻译为:一旦一个实例变为Inactive,则这个状态永远都不会再被改变。

以上就是Reference的4中状态的一个说明。

2.3 Reference属性的介绍

Reference属性的介绍

在Reference中,从数据结构上看,Reference链表结构内部主要有:

    private T referent;         /* Treated specially by GC */
    Reference next;//指向下一个

另一个相当重要的属性为:

  volatile ReferenceQueue<? super T> queue;

这个queue是通过构造函数传入的,表示创建一个Reference时,要将其注册到那个queue上。

Queue的另外一个作用是可以区分不同状态的Reference。Reference有4中状态。分别为:Active、Pending、Enqueued和Inactive状态,关于这4中状态的具体含义在本文上面已经进行了简单的介绍。而这4中状态所对应的Que

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值