JDK源码解析/深入理解Reference和ReferenceQueue

本文详细介绍了JDK中的Reference类型,包括其不同状态(Active、Pending、Enqueued、Inactive)及其转换过程,同时探讨了ReferenceQueue的使用和源码分析。通过测试代码和环境设置,展示了在限制内存环境下的行为分析。
摘要由CSDN通过智能技术生成

一、Reference简介

1.reference状态

Active:新创建的实例状态,当被垃圾收集器回收时,如果实例注册时候指定了队列,则变成Pending状态,否则变成Inactive状态。
Pending:pending-Reference列表的一个元素,等待被Reference-handler线程入队。解注册的实例不会是这种状态。
Enqueued:实例创建的时候指定的queue的一个元素,当实例从queue移除的时候,状态变成Inactive。解注册的实例不会是这种状态。
Inactive: 当一个实例的状态变成Inactive,它的状态永远不会改变。

2. 状态改变

如果初始化一个引用传入了ReferenceQueue,reference状态变化过程:Active->Pending->Enqueued->Inactive。
如果没有传入ReferenceQueue,Active->Inactive。没有入队的过程。

3.简单举例 

以弱引用举例,垃圾收集器工作,回收弱引用指向的对象(referent,referent状态变成finalizable)那一部分内存,由Reference-handler线程把pending状态的引用(reference)放入queue里面,然后把pending的discovered变成下一个pending。Reference-handler线程是一个高优先级的线程,并非是在垃圾回收器工作之后才去工作,而是一直等待着pending的值,有值就入队。

以下为猜想,帮助更好理解:如果有四个弱引用r1、r2、r3、r4,没有被回收,状态都为Active,r1->discovered=r2,r2->discovered=r3,r3->discovered=r4,进行GC,Reference的静态变量pending值被GC赋值为r1,r1的状态变成Pending,Reference-handler线程检测到pending被赋值,把r1放入queue,r1状态变成Enqueued,然后把pending的值改为r1的成员变量discovered的值,即r2,r2的状态被变成Pending,重复这个过程,r1、r2、r3、r4依次进入queue,状态都变成Enqueued,而r4的discovered为空,pending又为空,等待GC赋值。

二、ReferenceQueue简介

1.ReferenceQueue名字叫队列,实际是个栈,按照后入先出的方式处理引用,后面还是称呼队。
2.入队之后把引用内部的queue置为ENQUEUED,也就是一个空队列。如果引用的queue为空或者ENQUEUED则不处理。然后把当前引用的next指向之前的head,head指向当前引用。
3.出队就是把head弹出。出队有两种方法,一种head为空,一直等待。另一种是head为空,直接返回。
ReferenceQueue主要是用来追踪被GC掉的引用。比如WeakHashMap,把ReferenceQueue里面的引用key从Map里面删除。
如果引用从queue里面remove了,则状态变成Inactive。

三、Reference源码

public abstract class Reference<T> {

    /* A Reference instance is in one of four possible internal states:
     *
     *     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.
     *
     *     Pending: An element of the pending-Reference list, waiting to be
     *     enqueued by the Reference-handler thread.  Unregistered instances
     *     are never in this state.
     *
     *     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.
     *
     *     Inactive: Nothing more to do.  Once an instance becomes Inactive its
     *     state will never change again.
     *
     * The state is encoded in the queue and next fields as follows:
     *
     *     Active: queue = ReferenceQueue with which instance is registered, or
     *     ReferenceQueue.NULL if it was not registered with a queue; next =
     *     null.
     *
     *     Pending: queue = ReferenceQueue with which instance is registered;
     *     next = this
     *
     *     Enqueued: queue = ReferenceQueue.ENQUEUED; next = Following instance
     *     in queue, or this if at end of list.
     *
     *     Inactive: queue = ReferenceQueue.NULL; next = this.
     *
     * 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.
     *
     * 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.
     */

    private T referent;   // 引用的具体对象,被垃圾收集器回收,值为null      /* Treated specially by GC */

    volatile ReferenceQueue<? super T> queue; // 初始化的时候被设置

    /* 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 refer
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值