美文网首页
JAVA引用(WeakHashMap、Cleaner)

JAVA引用(WeakHashMap、Cleaner)

作者: cqxxxxxxxx | 来源:发表于2021-05-27 10:06 被阅读0次
    Expunge 删除,抹去
    stale   陈腐、老旧的
    

    Reference 引用类

    强引用、软引用、弱引用、虚引用

    软引用、弱引用、虚引用,可以配合ReferenceQueue实现对象被回收时候的监听

    Reference

    重要属性:

    1. private T referent;       
    weakHashMap中就是那个Entry的Key   Treated specially by GC
    
    2. volatile ReferenceQueue<? super T> queue;
    Reference队列,GC后Reference对象会被加到这里面,是放到队列头部。
    
    3. private static Lock lock = new Lock();
    GC时候必须要获得这个锁
    
    4. private static Reference<Object> pending = null;
    跟虚拟机,GC打交道的。 GC后Reference对象会被GC自动设置到这个引用中,然后由ReferenceHandler线程把他放到ReferenceQueue里面.
        
    5. transient private Reference<T> discovered; 
    跟虚拟机,GC打交道的  used by VM 
    
    6. volatile Reference next;
    ReferenceQueue是linkedList类似是实现,链表结构,Reference就相当于其中的Node,有一个next的指针指向下一个对象。
    

    ReferenceHandler 内部类:

    1. 在Reference类的静态代码块中初始化,然后运行。
    2. 主要功能是在tryHandlePending()方法中,把Reference类的静态变量pending指向的Reference对象丢到他自己的queue中。
    3. 于此同时,如果pending所指的Reference对象是Cleaner,那么还会执行Cleaner的clean方法,而且不会放到queue中,执行了clean方法后就返回了。

    Cleaner在DirectByteBuffer中有使用,下面介绍.

    Cleaner类

    public class Cleaner extends PhantomReference<Object> 集成虚引用, 也就是说cleaner的var0只要他强引用消失了,那么var0所指的对象就随时会被GC掉。

    //创建方法,add方法也是把cleaner自身构建成一个链表结构
    public static Cleaner create(Object var0, Runnable var1) {
       return var1 == null ? null : add(new Cleaner(var0, var1));
    }
    private Cleaner(Object var1, Runnable var2) {
       super(var1, dummyQueue);
       this.thunk = var2;
    }
    

    clean方法,在Reference的tryHandlePending方法中会执行,即Cleaner关联的对象被GC放到pending中,然后ReferenceHandler线程执行tryHandlePending时候执行。

        public void clean() {
            //删除自身节点
            if (remove(this)) {
                try {
                //执行创建时候传进来的runnable对象的run方法,执行相关的业务逻辑
                //比如DirectByteBuffer类中,他有个cleaner,run方法是用于释放直接内存
                //详见下
                    this.thunk.run();
                } catch (final Throwable var2) {
                    //省略。。。
                }
            }
        }
    

    Cleaner在DirectByteBuffer中有使用,下面介绍.

    DirectByteBuffer中Cleaner的使用

    DirectByteBuffer基于unsafe类的allocateMemory来分配直接内存使用。

    基于Cleaner来进行直接内存的释放。

    直接内存申请,释放流程:
    1. new DirectByteBuffer(1024)构建对象,构造方法内部调用Unsafe.allocateMemory申请到直接内存(不归JVM GC管辖)
    2. 构造方法内部还调用``Cleaner.create(this, new Deallocator(base, size, cap))`把当前DirectByteBuffer设置为虚引用,并设置一个Deallocator的runnable类。
    3. 当DirectByteBuffer强引用消失,即不可达之后,由于Cleaner是虚引用,不影响GC,所以DirectByteBuffer被GC掉了
    4. 与此同时,Cleaner对象也被GC设置到Reference的静态属性pending中(这个时候Cleaner即Reference的Referent引用指向的DirectByteBuffer已经是null了)
    5. Reference中的ReferenceHandler线程执行tryHandlePending,处理pending,即该Cleaner
    6. tryHandlePending中调用Cleaner的clean方法,clean方法内部调用构建时候传入的runnable对象的run方法,即Deallocator的run方法。
    7. Deallocator的run方法中调用了unsafe.freeMemory(address);来释放DirectByteBuffer在构建时候申请的直接内存
    8. 以此来完成直接内存的释放

    WeakHashMap

    https://hongjiang.info/java-referencequeue/

    以前设计缓存时也曾过用WeakHashMap来实现,对Java的Reference稍做过一些了解,其实这个问题,归根到底,是个Java GC的问题,由垃圾回收器与ReferenceQueue的交互方式决定的。WeakHashMap的实现也是通过ReferenceQueue这个“监听器”来优雅的实现自动删除那些引用不可达的key的。

    Entry类继承了WeakReference, 其中的Key是弱引用,并且WeakHashMap中定义了一个ReferenceQueue,用于监听key的回收

      //Entry类继承弱引用
      private static class Entry<K,V> extends WeakReference<Object> {}
      
      //WeakHashMap中的实例变量用于监听key的回收
      private final ReferenceQueue<Object> queue = new ReferenceQueue<>();
    
    流程
    1. 当WeakHashMap中Key没有其他强引用时候,发生了一次任意GC,由于Entry的Key是弱引用,那么被GC回收。

    2. 被GC回收的同时,Entry类(继承了弱引用)会由GC自动放入到Reference的静态属性pending中。

    3. Reference类在类初始化后有个static代码块,里面启动了一个高优先级的daemon线程,用于把pending指向的Reference对象放到ReferenceQueue中

    4. 经过3后,Entry就被丢到了ReferenceQueue中

    5. 当你在GC后调用WeakHashMap的get、put、size等方法时候,他会调用自己的expungeStaleEntries()方法。

    6. expungeStaleEntries方法会poll出queue中的Entry类,然后把entry类处理下,value=null,释放掉value的强引用,然后处理前后的指针,size--之类。

    7. 经过6之后,key对应的value强引用也被抹去了,所以GC也可以把value以及整个entry回收掉。

    相关文章

      网友评论

          本文标题:JAVA引用(WeakHashMap、Cleaner)

          本文链接:https://www.haomeiwen.com/subject/lkyrsltx.html