在了解
Weak
Reference
之前
,
先给出一段简单的代码
:
public
class
WeakReferenceTest {
public
static
void
main(String[] args) throws
Exception {
Object o = new
Object();
// 默认的构造函数,会使用ReferenceQueue.NULL 作为queue
WeakReference<Object> wr = new
WeakReference<Object>(o);
System.out.println(wr.get() == null);
o = null;
System.gc();
System.out.println(wr.get() == null);
}
}
输出结果
:false,true
喜欢探求究竟的童鞋会问
,
为啥
System
.gc
后
Weak
Reference
马上会被回收
,
怎么做到的呢
?
让我们一起来深入
Reference
的源码探求个究竟
.
内部有两点需要注意
:
1)
pending和 discovered成员:
先看
:pending
对象
/* 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.
*/
private
static
Reference pending = null;
这个对象,定义为private,并且全局没有任何给它赋值的地方,根据它上面的注释,我们了解到这个变量是和垃圾回收期打交道的
再看discovered,同样为private,上下文也没有任何地方使用它
transient
private
Reference<T> discovered; /* used by VM */
看到了它的注释也明确写着是给VM用的。
上面两个变量对应在VM中的调用,可以参考openjdk中的hotspot源码,在hotspot/src/share/vm/memory
/referenceProcessor.cpp 的ReferenceProcessor::discover_reference
方法。(根据此方法的注释由了解到虚拟机在对Reference的处理有ReferenceBasedDiscovery和
RefeferentBasedDiscovery两种策略)
2)
ReferenceHandler 线程
这个线程在Reference类的static构造块中启动,并且被设置为高优先级和daemon状态。
此线程要做的事情,是不断的检查pending 是否为null,如果pending不为null,则将pending进行enqueue,否则线程进入wait状态。
通过这2点,我们来看整个过程:
pending是由jvm来赋值的,当Reference内部的referent对象的可达状态改变时,jvm会将Reference对象放入pending链表。
结
合代码eg1中的 o = null; 这一句,它使得o对象满足垃圾回收的条件,并且在后边显式的调用了
System.gc(),垃圾收集进行的时候会标记WeakReference所referent的对象o为不可达(使得
wr.get()==null),并且通过 赋值给pending ,触发ReferenceHandler线程处理pending。
ReferenceHandler
线程要做的是将pending对象enqueue,但默认我们所提供的queue,也就是从构造函数传入的是null,实际是使用了
ReferenceQueue.NULL,Handler线程判断queue为ReferenceQueue.NULL则不进行操作,只有非
ReferenceQueue.NULL 的queue才会将Reference进行enqueue。
ReferenceQueue.NULL相当于我们提供了一个空的Queue去监听垃圾回收器给我们的反馈
(
什么反馈呢
?
是说这个
quene
是给我们来用的么
,
例如
WeakHashMap
中使用的那种方式
)
,并且对这种反馈不做任何处理。
(
但垃圾还是回收了
???
不是
poll
时候做的事情么
?)
要处理反馈,则必须要提供一个非ReferenceQueue.NULL的queue。这个quene可以看做是GC与应用程序的一个桥梁,告知应用需要对那些reference进行处理.
当一个
WeakReference
开始返回
null
时,
它所指向的对象已经准备被回收,
这时可以做一些合适的清理工作
.
将一个
ReferenceQueue
传给一个
Reference
的构造函数,
当对象被回收时,
虚拟机会自动将这个对象插入到
ReferenceQueue
中,
WeakHashMap
就是利用
ReferenceQueue
来清除
key
已经没有强引用的
entries.
在WeakHashMap则在内部提供了一个非NULL的ReferenceQueue
private
final
ReferenceQueue<K> queue = new
ReferenceQueue<K>();
在 WeakHashMap 添加一个元素时,会使用 此queue来做监听器。
见put方法中的下面一句:
tab[i] = new
Entry<K,V>(k, value, queue, h, e);
这里Entry是一个内部类,继承了WeakReference
class
Entry<K,V> extends
WeakReference<K> implements
Map.Entry<K,V>
WeakHashMap的 put, size, clear 都会间接或直接的调用到 expungeStaleEntries()方法。
顾名思义,此方法的作用就是将 queue中陈旧的Reference进行删除,因为其内部的referent都已经不可达了。所以也将这个WeakReference包装的key从map中删除。
总结:ReferenceQueue是作为 JVM GC与上层Reference对象管理之间的一个消息传递方式,它使得我们可以对所监听的对象引用可达发生变化时做一些处理,WeakHashMap正是利用此来实现的。
用图来大致表示如下:
分享到:
相关推荐
我们平常用的都是对象的强引用,如果有强引用存在,GC是不会回收对象的。我们能不能同时保持对对象的引用,而又可以让GC需要的时候回收这个对象呢?.NET中提供了WeakReference来实现。弱引用可以让您保持对对象的...
StrongReference,SoftReference, WeakReference的使用实例,请参照博客:http://blog.csdn.net/To_be_Designer/article/details/72673421
SoftReference、WeakReference和PhantomRefrence分析和比较
这个项目为万能的(有时是可怕的)弱引用实现了一个kotlin包装器,以便您可以更友好地使用它们。
3.1 强引 3.2 软引 3.3 弱引 3. 4 假象引
AsyncTask_WeakReference
主要介绍了Java弱引用(WeakReference)的理解与使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
A:通过WeakReference构造出的,不再有强引用… Q:那软引用呢,这些引用间的区别是什么? A:… 面到这个阶段这比较尴尬了。为了避免类似的尴尬,特地花了点时间去整理这些引用,以便下次面试的时候这...
创建用于WPF MVVM绑定的Singleton,并对绑定的属性使用弱引用的概念。
这是对 java.lang.ref.WeakReference 实现的修改,它将通过 JMX MBean 跟踪和报告它发现的内容。如何使用: 在您的应用程序中启用 JMX。 然后使用指向此实现的引导类路径启动 Java 应用程序。 例如: $ java -...
他们分别是强引用(StrongReference),软引用(SoftReference),弱引用(WeakReference)以及PhantomReference(虚引用),他们被 GC回收的可能性从小到大排列。 强引用(StrongReference) 只要强引用存在,垃圾回收器将...
放在了这里,有兴趣的可以看下原理简单点说就是: 在onDestroy的时候为Activity加上WeakReference,然后在合适的时机调用Runtime.getRuntime().gc()触发GC,之后检测下WeakReference还是否存在。如果存在,那么...
弱参考测试 代码测试 ...或在命令行上创建一个新的存储库 touch README.md git init git add README.md git commit -m "first commit" git remote add origin git push -u origin master ......git remote add origin ...
Java中的弱引用具体指的是java.lang.ref.WeakReference类,我们首先来看一下官方文档对它做的说明: 弱引用对象的存在不会阻止它所指向的对象变被垃圾回收器回收。弱引用常见的用途是实现规范映射...
ava有四种引用类型,strongreference,softreference,weakreference,phantomreference。本篇文档主要的就是进阶的介绍和了解这四种引用类型的异同点,助于你对java的更好的学习理解
├─Google Guava 第29讲-SoftReference,WeakReference,PhantomReference精讲.wmv ├─Google Guava 第30讲-SoftReference加LRU算法实现InMemoryCache.wmv ├─Google Guava 第31讲-Guava之CacheLoader,...
前述:除了强引用外,其他引用不是我们所常见的 new出来的对象,而是需要借用3个类SoftReference软引用,WeakReference弱引用,PhantomReference虚引用 1.强引用 概述:即发生OOM(Out Of Memory)内存空间满了也...
import java.lang.ref.WeakReference; import android.app.Activity; import android.content.ContentResolver; import android.content.ContentValues; import android.database.Cursor; import android.net.Uri; ...