WeakHashMap与Java引用相关

记得在很久之前有写过一篇《Java中的Reference解析》,主要讲的是Java中的四种引用方式与引用队列,不过这些都是基础的理论知识,最近开发项目中有使用到WeakHashMap,对于Java的引用以及引用队列有了更深的了解,在此做个相关总结。

一、WeakHashMap的实现方式

总体来说,WeakHashMap的底层数据结构与HashMap的实现差不多,都是用“拉链法”来实现,主要区别在于WeakHashMap的Entry 继承于WeakReference,并维护一个ReferenceQueue,使其具有了“弱引用的特性”,其构造方法可以看出:

Entry(Object key, V value,ReferenceQueue<Object> queue,int hash, Entry<K,V> next) {
            super(key, queue); //这里比较关键
            ……
        }

其中的super父类的代码实现为:

public WeakReference(T referent, ReferenceQueue<? super T> q) {
        super(referent, q);
    }

通过对父类的构造方法可以知道,WeakMap的key值为弱引用类型,回顾一下弱引用的特点:垃圾收集器工作时,无论当前内存是否足够,都会回收掉只被弱引用关联的对象。 于是WeakHashMap的作用就凸显出来了:**对于数据中Key-value,key因为使用的弱引用会被回收,而value也会得到对应的释放。**以我这次的需求为例:key为Webview页面或者Flutter/RN页面,value为调用native方法相关存储的对象。当页面需要关闭调webivew的时候,Webview应该要被释放,要不然会产生内存泄漏,当其被释放之后,对应的value也没有意义了,所以也需要被释放掉。

那么WeakHashMap是如何让value释放的呢?

二、WeakHashMap如何释放无用的Value

要回收无用的Value,那么引用队列(ReferenceQueue)就派上用场了,回顾一下引用队列的作用:当一个引用(软引用、弱引用)关联到了一个引用队列后,当这个引用所引用的对象要被垃圾回收时,就会将它加入到所关联的引用队列中。
所以判断一个引用对象是否已经被回收的一个现象就是,这个对象的引用是否被加入到了它所关联的引用队列。
那么对于WeakHashMap也是利用这一点特性,在其代码中put\get等方法都有执行对应等检查

 public V put(K key, V value) {
        Object k = maskNull(key);
        int h = hash(k);
        Entry<K,V>[] tab = getTable(); //具体实现在getTable执行的expungeStaleEntries里面
        ……
    public V get(Object key) {
        Object k = maskNull(key);
        int h = hash(k);
        Entry<K,V>[] tab = getTable();
        ……
    /**
     * Expunges stale entries from the table.
     */
    private void expungeStaleEntries() {
        for (Object x; (x = queue.poll()) != null; ) { //这里的queue就是引用队列
            synchronized (queue) { 
                @SuppressWarnings("unchecked")
                    Entry<K,V> e = (Entry<K,V>) x;
                int i = indexFor(e.hash, table.length);

                Entry<K,V> prev = table[i];
                Entry<K,V> p = prev;
                while (p != null) {
                    Entry<K,V> next = p.next;
                    if (p == e) {
                        if (prev == e)
                            table[i] = next;
                        else
                            prev.next = next;
                        // Must not null out e.next;
                        // stale entries may be in use by a HashIterator
                        e.value = null; // Help GC
                        size--;
                        break;
                    }
                    prev = p;
                    p = next;
                }
            }
        }
    }

从上面的代码逻辑可以很清楚的知道:WeakHashMap通过对引用队列的数据进行检查,对key被回收对象的对应Value进行了回收。

三、总结

1、WeakHashMap的Entry 继承于WeakReference,并维护一个ReferenceQueue
2、在执行get\put等相关数据操作的时候 会对数据进行相关处理,主要是清除掉无用对象对

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值