`

WeakReference &&reference quene &&GC

阅读更多

在了解 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正是利用此来实现的。

 

用图来大致表示如下:


分享到:
评论

相关推荐

    WeakReference(弱引用)让GC需要时回收对象

    我们平常用的都是对象的强引用,如果有强引用存在,GC是不会回收对象的。我们能不能同时保持对对象的引用,而又可以让GC需要的时候回收这个对象呢?.NET中提供了WeakReference来实现。弱引用可以让您保持对对象的...

    SoftReference、WeakReference和PhantomRefrence分析和比较

    SoftReference、WeakReference和PhantomReference分析和比较 在 Java 中,引用类型分为强引用、软引用、弱引用和虚引用四种。强引用是我们最常用的引用类型,而软引用、弱引用和虚引用则是 Java 为我们提供的三种...

    StrongReference,SoftReference, WeakReference的使用实例

    StrongReference,SoftReference, WeakReference的使用实例,请参照博客:http://blog.csdn.net/To_be_Designer/article/details/72673421

    Java引用总结--StrongReference、SoftReference、WeakReference、PhantomRef

    Java从1.2版本开始引入了四种引用,分别是强引用(StrongReference)、软引用(SoftReference)、弱引用(WeakReference)和虚引用(PhantomReference)。这四种引用的级别由高到低依次为:强引用 &gt; 软引用 &gt; 弱引用...

    Java功底之Reference

    `Reference`类及其子类主要用于处理对象的软引用、弱引用和虚引用,这些引用类型在内存管理,特别是垃圾收集(Garbage Collection,GC)中扮演着关键角色。本文将深入探讨`Reference`类及其相关知识点。 首先,我们...

    WeakDelegate,Weakreference财产委托提议.zip

    在IT行业中,尤其是在Android或Java开发中,弱引用(WeakReference)是一个重要的概念,它用于内存管理,防止内存泄漏。这个“WeakDelegate,Weakreference财产委托提议.zip”项目显然是一个Kotlin实现的开源项目,旨在...

    C#垃圾回收机制GC

    主流的垃圾回收算法有Reference Counting、Mark Sweep和Copy Collection,其中.NET采用的是Mark-Compact算法。 Mark-Compact算法分为两步: 1. Mark-Sweep(标记清除):首先假设所有对象都可回收,然后从根开始...

    JAVA GC 与 JVM调优1

    创建弱引用的代码示例:`WeakReference&lt;Object&gt; wf = new WeakReference(obj);` 4. **虚引用**(Phantom Reference)或幽灵/幻影引用:虚引用在对象被垃圾回收后才能被感知,无法直接获取对象,只能用来判断对象...

    详解Java弱引用(WeakReference)的理解与使用

    弱引用和强引用(StrongReference)的区别在于:当一个对象仅仅被弱引用指向,而没有任何其他强引用指向时,如果 GC 运行,那么该对象就会被回收。弱引用的语法是:`WeakReference&lt;Car&gt; weakCar = new WeakReference...

    AsyncTask_WeakReference

    `WeakReference`是Java和Kotlin中处理引用的一种机制,它可以帮助我们防止内存泄漏。在`AsyncTask`与`WeakReference`结合使用时,可以确保当Activity或Fragment被销毁时,相关任务不会因为强引用而继续存在,从而...

    Java Reference源码解析

    * `referent`:用于保存对象的引用,GC会根据不同Reference来特别对待。 * `queue`:如果需要通知机制,则保存的对对应的队列。 * `next`:用于实现一个单向循环链表,用以将保存需要由ReferenceHandler处理的引用。...

    Java的GC机制探微.pdf

    - SoftReference、WeakReference和PhantomReference的使用不当。 - 大对象直接进入老年代,可能导致频繁的Major GC。 - 类加载器未正确卸载,导致方法区内存泄漏。 7. **JVM内存监控工具** - **jconsole**:...

    一篇文章教你深入理解Java垃圾收集(GC)机制.docx

    - 弱引用:通过WeakReference实现,无论内存是否充足,下次GC时都会回收弱引用对象。 - 虚引用:通过PhantomReference实现,仅用于在对象被回收时获取通知,不影响对象的生命周期。 3. **垃圾收集算法** - 标记...

    C#中实现内存回收

    - 使用弱引用(WeakReference)来避免对象被无意间保持活动状态,导致内存泄漏。 - 考虑使用池化技术,如对象池,减少频繁的对象创建和销毁。 总之,C#中的垃圾回收是一个自动过程,但开发者可以通过理解其原理和...

    Java中的软引用弱引用和虚引用.docx

    本文将深入探讨Java中三种特殊的引用类型——软引用(Soft Reference)、弱引用(Weak Reference)以及虚引用(Phantom Reference),并分析它们如何帮助我们更好地管理内存资源。 #### 二、基础知识回顾 在深入了解这三...

    Java 中 Reference用法详解

    WeakReference&lt;Object&gt; weakRef = new WeakReference(obj); 在上面的代码中,weakRef 是一个弱引用,它会在垃圾回收器发现弱引用对象时将其回收。 虚引用(Phantom Reference) 虚引用是一种特殊的引用类型,它会...

    WPF MVVM视图绑定到单例和WeakReference

    在这个场景中,标题“WPF MVVM视图绑定到单例和WeakReference”涉及到两个关键概念:单例模式和弱引用。 首先,单例模式是一种设计模式,确保一个类只有一个实例,并提供全局访问点。在C#中,我们通常通过静态方法...

    详解java中Reference的实现与相应的执行过程

    3. **WeakReference**:弱引用对象会在下一次垃圾收集时立即被回收,无论内存是否充足。适用于不希望阻止对象被回收的情况,例如,防止内存泄漏的缓存实现。 4. **FinalReference**:专为 `finalize()` 方法设计,...

Global site tag (gtag.js) - Google Analytics