WeakHashMap与Java引用相关
记得在很久之前有写过一篇《Java中的Reference解析》,主要讲的是Java中的四种引用方式与引用队列,不过这些都是基础的理论知识,最近开发项目中有使用到WeakHashMap,对于Java的引用以及引用队列有了更深的了解,在此做个相关总结。
一、WeakHashMap的实现方式
总体来说,WeakHashMap的底层数据结构与HashMap的实现差不多,都是用“拉链法”来实现,主要区别在于WeakHashMap的Entry 继承于WeakReference,并维护一个ReferenceQueue,使其具有了“弱引用的特性”,其构造方法可以看出:
1 | Entry(Object key, V value,ReferenceQueue<Object> queue,int hash, Entry<K,V> next) { |
其中的super父类的代码实现为:
1 | public WeakReference(T referent, ReferenceQueue<? super T> 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等方法都有执行对应等检查
1 | public V put(K key, V value) { |
1 | public V get(Object key) { |
1 | /** |
从上面的代码逻辑可以很清楚的知道:WeakHashMap通过对引用队列的数据进行检查,对key被回收对象的对应Value进行了回收。
三、总结
1、WeakHashMap的Entry 继承于WeakReference,并维护一个ReferenceQueue
2、在执行get\put等相关数据操作的时候 会对数据进行相关处理,主要是清除掉无用对象对