【JVM从小白学成大佬】3.深入解析强引用、软引用、弱引用、幻象引用

  • 时间:
  • 浏览:25
  • 来源:大发uu快3_uu快3遗漏_大发uu快3遗漏

关于强引用、软引用、弱引用、幻象引用的区别,在什么都公司的面试题中时不时时不时冒出,原因否则 小伙伴真是 你有一种知识点比较冷门,但真是 大伙在开发中时不时用到,如new另4个 对象的时候什么都强引用的应用。

在java语言中,除了原始数据类型(boolean、byte、short、char、int、float、double、long)的变量,否则 所有有的是所谓的引用类型,指向各种不同的对象。理解那先 引用的区别,对于掌握java对象生命周期和JVM外部相关机制非常有帮助。有的是有益于更深刻的理解底层对象生命周期、垃圾收集机制等,对设计可靠的缓存框架、诊断应用OOM等问提也大有裨益。

你有一种种生活应用主要的区别体现在对象不同的可达性请况和对垃圾收集的影响,大伙之间的可达性请况可不想能不能 参看下图:

1.强引用(strong reference)

强引用什么都大伙最常见的普通对象引用(如new 另4个 对象),只要还有强引用指向另4个 对象,就表明此对象还“活着”。在强引用眼前 ,即使JVM内存空间严重不足,JVM宁愿抛出OutOfMemoryError运行时错误(OOM),让应用守护进程异常终止,什么都会靠回收强引用对象来处里内存严重不足的问提。对于另4个 普通的对象,原因这麼否则 的引用关系,只要超过了引用的作用域原因显式地将相应(强)引用赋值为null,就原因此对象可不想能不能 被垃圾收集了。但要注意的是,并有的是赋值为null后就立马被垃圾回收,具体的回收时机还是要看垃圾收集策略的。

如Object obj = new Object();

2.软引用(soft reference)

软引用相对强引用要弱化否则 ,可不想能不能 让对象豁免否则 垃圾收集。当内存空间足够的时候,垃圾回收器不想回收它。不到当JVM认定内存空间严重不足时才会去回收软引用指向的对象。JVM会确保在抛出OOM前清理软引用指向的对象,否则JVM是很聪明的,会尽原因优先回收长时间闲置不想的软引用指向的对象,对那先 刚构建的或刚使用过的软引用指向的对象尽原因的保留。基于软引用的那先 外部,软引用可不想能不能 用来实现什么都内存敏感点的缓存场景,即原因内存还有空闲,可不想能不能 暂时缓存否则 业务场景所需的数据,当内存严重不足时就可不想能不能 清理掉,等上边再不能不能 时,可不想能不能 重新获取并再次缓存。从前就确保在使用缓存提升性能的一齐,不想原因耗尽内存。

软引用通常可不想能不能 和另4个 引用队列(ReferenceQueue)联合使用,原因弱引用所引用的对象被垃圾回收,java虚拟机就会把你有一种软引用加入到与之关联的引用队列中。

Object obj = new Object();
SoftReference<Object> sf = new SoftReference<Object>(obj);
obj = null;
//有时候要返回null
sf.get(); 

通过上边的代码可不想能不能 看出sf是对obj的另4个 软引用,当sf对象还这麼被销毁前,sf.get()可不想能不能 获取到你有一种对象,原因已被销毁,则返回null。

正确使用软引用的示例代码如下:

SoftReference<List<Foo>> ref = new SoftReference<List<Foo>>(new LinkedList<Foo>());
 
// somewhere else in your code, you create a Foo that you want to add to the list
List<Foo> list = ref.get();
if (list != null)
{
    list.add(foo);
}
else
{
    // list is gone; do whatever is appropriate
} 

在使用软引用的时候不能不能 检查引用算是为null。原因垃圾收集器原因在任意时刻回收软引用,原因不做算是null的判断,原因会时不时冒出NullPointerException的异常。

总的来说,软引用是用来描述否则 还有用但无须必需的对象。对于软引用关联着的对象,在系统将要所处内存溢出异常时候,原因把那先 对象列进回收范围之中进行第二次回收。原因这次回收还这麼足够的内存,才会抛出内存溢出异常。

3.弱引用(weak reference)

弱引用指向的对象是有有一种十分临近finalize请况的请况,当弱引用被清除的时候,就符合finalize的条件了。弱引用与软引用最大的区别什么都弱引用比软引用的生命周期更短暂。垃圾回收器会扫描它所管辖的内存区域的过程中,只要发现弱引用的对象,不管内存空间算是有空闲,有的是立刻回收它。如同前面你说歌词 过的,具体的回收时机还是要看垃圾回收策略的,否则那先 弱引用的对象并有的是说只要达到弱引用请况就会立马被回收。

基于弱引用的那先 外部,弱引用同样可不想能不能 应用在什么都不能不能 缓存的场景。

Object obj = new Object();
WeakReference<Object> wf = new WeakReference<Object>(obj);
obj = null;
//有时候要返回null
wf.get();
//返回算是被垃圾回收器标记为即将回收的垃圾
wf.isEnQueued();

4.幻象引用(phantom reference)

幻象引用,有的是被说成是虚引用或疾速引用。幻象引用无须会决定对象的生命周期。即原因另4个 对象仅持有虚引用,就大约这麼任何引用一样,在任何时候都原因被垃圾回收器回收。不到通过它访问对象,幻象引用仅仅是提供了有有一种确保对象被finalize时候,做否则 事情的机制(如做所谓的Post-Mortem清理机制),有的是人利用幻象引用监控对象的创建和销毁。

Object obj = new Object();
PhantomReference<Object> pf = new PhantomReference<Object>(obj);
obj=null;
//永远返回null
pf.get();
//返回算是从内存中原因删除
pf.isEnQueued(); 

幻象引用的get办法永远返回null,主要用于检查对象算是原因从内存中删除。

5.生存还是死亡

通过上边对有有一种引用类型的分析,你原因发现否则 对象即使不可达,但也无须是“非死不可”的,你有一种时候它们暂时所处“缓刑”阶段,要真正否认另4个 对象死亡,大约要经历两次标记过程原因对象在进行可达性分析后发现这麼与GC Roots相连接的引用链,那它原因被第一次标记否则进行一次筛选,筛选的条件是此对象算是有必要执行finalize()办法。当对象这麼覆盖finalize()办法,原因finalize()办法原因被虚拟机调用过,虚拟机将你有一种种生活请况都视为“这麼必要执行”。

原因你有一种对象被判定为有必要执行finalize()办法,这麼你有一种对象原因放置在另4个 叫做F-Queue的队列之中,并在稍后被另4个 由虚拟机自动建立的、低优先级的Finalizer应用守护进程去执行它。这里所谓的“执行”是指虚拟原因触发你有一种办法,但无须承诺会等待英文它运行结束,从前做的原因是,原因另4个 对象在finalize()办法中执行缓慢,原因所处了死循环(更极端的请况),将很原因会原因F-Queue队列中否则 对象永久所处等待英文,甚至原因整个内存回收系统奔溃。finalize()办法是对象逃脱死亡命运的最后一次原因,稍后GC将对F-Queue中的对象进行第二次小规模的标记,原因对象要在finalize()中成功拯救当时人——只要重新与引用链上的任何另4个 对象建立关联即可。譬如把当时人(this关键字)赋值给某个类变量原因对象的成员变量,那在第二次标记时它将被移除出“即将回收”的集合;原因对象这时候还这麼逃脱,那基本上它就真的被回收了。

任何另4个 对象的finalize()办法都只会被系统自动调用一次,原因对象面临下一次回收,它的finalize()办法不想被再次执行。

6.总结

对象的可达性是JVM垃圾收集器决定何如处里对象的另4个 重要考虑指标

所有引用类型有的是抽象类java.lang.ref.Reference的子类,子类里提供了get()办法。通过上边的分析中可不想能不能 得知,除了幻象引用(原因get永远返回null),原因对象还这麼被销毁,都可不想能不能 通过get办法获取原有对象。真是 有个非常关键的注意点,利用软引用和弱引用,大伙可不想能不能 将访问到的对象,重新指向强引用,也什么都人为的改变了对象的可达性请况。什么都对于软引用、弱引用什儿 ,垃圾收集器原因会所处二次确认的问提,以确保所处弱引用请况的对象这麼改变为强引用。

否则有个问提,原因大伙错误的保持了强引用(比如,赋值给了static变量),这麼对象原因就这麼原因变回什儿 弱引用的可达性请况了,就会产生内存泄露。什么都,检查弱引用指向对象算是被垃圾收集,也是诊断算是有特定内存泄露的另4个 思路,大伙的框架使用到弱引用又怀疑有内存泄露,就可不想能不能 从你有一种高度检查。

对于软引用、弱引用、幻象引用可不想能不能 配合引用队列(ReferenceQueue)来使用,有点是幻象引用,get办法只返回null,原因再不指定引用队列,基本就这麼任何意义了。

上边分析了有有一种引用类型的使用,熟悉这几种应用类型对深入理解JVM也大有裨益。

热门阅读:

【JVM从小白学成大佬】1.开篇【JVM从小白学成大佬】2.Java虚拟机运行时数据区

参考

《深入理解Java虚拟机》

http://www.kdgregory.com/index.php?page=java.refobj