在了解
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来实现。弱引用可以让您保持对对象的...
SoftReference、WeakReference和PhantomReference分析和比较 在 Java 中,引用类型分为强引用、软引用、弱引用和虚引用四种。强引用是我们最常用的引用类型,而软引用、弱引用和虚引用则是 Java 为我们提供的三种...
StrongReference,SoftReference, WeakReference的使用实例,请参照博客:http://blog.csdn.net/To_be_Designer/article/details/72673421
Java从1.2版本开始引入了四种引用,分别是强引用(StrongReference)、软引用(SoftReference)、弱引用(WeakReference)和虚引用(PhantomReference)。这四种引用的级别由高到低依次为:强引用 > 软引用 > 弱引用...
`Reference`类及其子类主要用于处理对象的软引用、弱引用和虚引用,这些引用类型在内存管理,特别是垃圾收集(Garbage Collection,GC)中扮演着关键角色。本文将深入探讨`Reference`类及其相关知识点。 首先,我们...
在IT行业中,尤其是在Android或Java开发中,弱引用(WeakReference)是一个重要的概念,它用于内存管理,防止内存泄漏。这个“WeakDelegate,Weakreference财产委托提议.zip”项目显然是一个Kotlin实现的开源项目,旨在...
主流的垃圾回收算法有Reference Counting、Mark Sweep和Copy Collection,其中.NET采用的是Mark-Compact算法。 Mark-Compact算法分为两步: 1. Mark-Sweep(标记清除):首先假设所有对象都可回收,然后从根开始...
创建弱引用的代码示例:`WeakReference<Object> wf = new WeakReference(obj);` 4. **虚引用**(Phantom Reference)或幽灵/幻影引用:虚引用在对象被垃圾回收后才能被感知,无法直接获取对象,只能用来判断对象...
弱引用和强引用(StrongReference)的区别在于:当一个对象仅仅被弱引用指向,而没有任何其他强引用指向时,如果 GC 运行,那么该对象就会被回收。弱引用的语法是:`WeakReference<Car> weakCar = new WeakReference...
`WeakReference`是Java和Kotlin中处理引用的一种机制,它可以帮助我们防止内存泄漏。在`AsyncTask`与`WeakReference`结合使用时,可以确保当Activity或Fragment被销毁时,相关任务不会因为强引用而继续存在,从而...
* `referent`:用于保存对象的引用,GC会根据不同Reference来特别对待。 * `queue`:如果需要通知机制,则保存的对对应的队列。 * `next`:用于实现一个单向循环链表,用以将保存需要由ReferenceHandler处理的引用。...
- SoftReference、WeakReference和PhantomReference的使用不当。 - 大对象直接进入老年代,可能导致频繁的Major GC。 - 类加载器未正确卸载,导致方法区内存泄漏。 7. **JVM内存监控工具** - **jconsole**:...
- 弱引用:通过WeakReference实现,无论内存是否充足,下次GC时都会回收弱引用对象。 - 虚引用:通过PhantomReference实现,仅用于在对象被回收时获取通知,不影响对象的生命周期。 3. **垃圾收集算法** - 标记...
- 使用弱引用(WeakReference)来避免对象被无意间保持活动状态,导致内存泄漏。 - 考虑使用池化技术,如对象池,减少频繁的对象创建和销毁。 总之,C#中的垃圾回收是一个自动过程,但开发者可以通过理解其原理和...
本文将深入探讨Java中三种特殊的引用类型——软引用(Soft Reference)、弱引用(Weak Reference)以及虚引用(Phantom Reference),并分析它们如何帮助我们更好地管理内存资源。 #### 二、基础知识回顾 在深入了解这三...
WeakReference<Object> weakRef = new WeakReference(obj); 在上面的代码中,weakRef 是一个弱引用,它会在垃圾回收器发现弱引用对象时将其回收。 虚引用(Phantom Reference) 虚引用是一种特殊的引用类型,它会...
3. **WeakReference**:弱引用对象会在下一次垃圾收集时立即被回收,无论内存是否充足。适用于不希望阻止对象被回收的情况,例如,防止内存泄漏的缓存实现。 4. **FinalReference**:专为 `finalize()` 方法设计,...
这些引用类型主要包括`StrongReference`、`WeakReference`、`SoftReference`和`PhantomReference`,每种都有其特定的用途和行为。 1. **StrongReference**: 强引用是Java中最常见的引用类型,由默认的赋值操作...