JVM之Reference源码分析

本文基于JDK1.8.0_271分析,native源码下载自openJDK官网(build 1.8.0_41-b04)

0. 前言

JDK1.2开始,引入了一个新的包,java.lang.ref

  • java.lang.ref
    • Finalizer.class
    • FinalizerHistogram.class
    • FinalReference.class
    • PhantomReference.class
    • Reference.class
    • ReferenceQueue.class
    • SoftReference.classs
    • WeakReference.class
  • 额外的还有一个在sun.misc包下
    • Cleaner.class

随之带来了四个新的概念:

  • 强引用Storn References:随处可见,我们直接new出来的代码就是强引用。内存不足时,宁愿抛出OutOfMemoryError也不愿意回收这些对象。我们可以手动的设置为null让GC回收他。
  • 软引用SoftReference:等级比强引用低,只有在内存不足的时候才回去回收。我们可以实现内存敏感的高速缓存。
  • 弱引用WeakReference:等级比软引用低,不管内存足不足,发生GC时,就有可能被回收。如果这个对象是一个偶尔使用的对象,并且需要在使用的时候就能获取到,但又不想影响生命周期,就可以使用WeakReference,比如处理内部类内存泄漏的问题时。
  • 虚引用PhantomReference:等级比弱引用低,形同虚设,任何时候都可能被回收。它可以和引用队列配合用于监控对象是否被回收

并且,除了强引用之外,其他三个都可以和引用队列配合使用,就是在调用他们的构造方法时,除了传入Object外,还可以传入一个ReferenceQueue,他的作用就是当Object被回收时,JVM会自动帮我们把这个软/弱/虚引用添加到这个Queue中。通过这个功能可以监控对象是否被回收。

直到JDK8为止,只存在四种引用,这些引用是由JVM创建,因此直接继承java.lang.ref.Reference创建自定义的引用类型是无效的,但是可以直接继承已经存在的引用类型,如sun.misc.Cleaner就是继承自java.lang.ref.PhantomReference

接下来我们就可以源码,但是在此之前,我们得带着问题看:

  • 软引用是内存不足才会回收,那么什么叫内存不足?
  • 弱引用只要发生GC时就回收,但是他不是引用着对应的强引用,那么他为啥能被回收?
  • 虚引用形同虚设,任何时候都会被回收,那么到底什么时候会被回收?
  • 当引用对象被回收时,他们是怎么被添加到若引用队列的?

1. Reference.java

1.1 源码

首先来看下他的构造方法和成员变量:

public abstract class Reference<T> {
   
    private T referent;         /* Treated specially by GC */
		volatile ReferenceQueue<? super T> queue;
    @SuppressWarnings("rawtypes")
    volatile Reference next;
    transient private Reference<T> discovered;  /* used by VM */
    static private class Lock {
    }
    private static Lock lock = new Lock();
    private static Reference<Object> pending = null;

    Reference(T referent) {
   
        this(referent, null);
    }

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

1.1.1 构造方法

构造方法有两种,一种只传入referent,另一种还要传入一个Queue,如果传入的queue为null的话,成员变量queue就等于ReferenceQueue.NULL

1.1.2 成员变量

  • reference:代表我们传入的对象。

  • queue: ReferenceQueue,就是引用队列。

    volatile ReferenceQueue<? super T> queue;
    
  • next:下一个Reference实例的引用,主要是在ReferenceQueue中使用。

    /* When active:   NULL
     *     pending:   this
     *    Enqueued:   next reference in queue (or this if last)
     *    Inactive:   this
     */
    @SuppressWarnings("rawtypes")
    volatile Reference next;
    
  • discovered:注意这个属性由transient修饰,基于状态表示不同链表中的下一个待处理的对象,主要是PendingList的下一个元素,通过JVM直接调用赋值。

    /* 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
     */
    private transient Reference<T> discovered;
    
  • 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.
     */
    static private class Lock {
          }
    private static Lock lock = new Lock();
    
  • pending:等待加入queue的Reference对象,在GC时由JVM设置,会有一个java层的线程(ReferenceHandler)源源不断从PendingList中取出元素加入到queue中

    /* 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.
     */
    private static Reference<Object> pending = null;
    

1.1.3 方法

/**
 * 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
 */
// 获取referent实例
@HotSpotIntrinsicCandidate
public T get() {
   
    return this.referent;
}

/**
 * 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.
 */
// 清除referent实例
public void clear(
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值