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

  • 时间:
  • 浏览:2
  • 来源:大发快3_快3网站地址_大发快3网站地址

关于强引用、软引用、弱引用、幻象引用的区别,在某些某些公司的面试题中突然突然出现,有日后某些小伙伴着实这人知识点比较冷门,但着实让我们歌词 都都 在开发中突然用到,如new另另俩个 对象的日后某些某些我强引用的应用。

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

这这人应用主要的区别体现在对象不同的可达性清况 和对垃圾收集的影响,让我们歌词 都都 之间的可达性清况 还都可不都可不可以参看下图:

1.强引用(strong reference)

强引用某些某些我让我们歌词 都都 最常见的普通对象引用(如new 另另俩个 对象),假如还有强引用指向另另俩个 对象,就表明此对象还“活着”。在强引用面前,即使JVM内存空间缺陷,JVM宁愿抛出OutOfMemoryError运行时错误(OOM),让任务管理器异常终止,某些某些我会靠回收强引用对象来避免内存缺陷的问题图片。对于另另俩个 普通的对象,有日后没有某些的引用关系,假如超过了引用的作用域有日后显式地将相应(强)引用赋值为null,就愿因此对象还都可不都可不可以被垃圾收集了。但要注意的是,并有的是赋值为null后就立马被垃圾回收,具体的回收时机还是要看垃圾收集策略的。

如Object obj = new Object();

2.软引用(soft reference)

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

软引用通常还都可不都可不可以和另另俩个 引用队列(ReferenceQueue)联合使用,有日后弱引用所引用的对象被垃圾回收,java虚拟机就会把这人软引用加入到与之关联的引用队列中。

Object obj = new Object();
SoftReference<Object> sf = new SoftReference<Object>(obj);
obj = null;
//有之一定会返回null
sf.get(); 

通过上边的代码还都可不都可不可以看出sf是对obj的另另俩个 软引用,当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)

幻象引用,有的是被说成是虚引用或疾驰引用。幻象引用何必 会决定对象的生命周期。即有日后另另俩个 对象仅持有虚引用,就大约没有任何引用一样,在任何日后都有日后被垃圾回收器回收。没有通过它访问对象,幻象引用仅仅是提供了这人确保对象被finalize日后,做某些事情的机制(如做所谓的Post-Mortem清理机制),有的是人利用幻象引用监控对象的创建和销毁。

Object obj = new Object();
PhantomReference<Object> pf = new PhantomReference<Object>(obj);
obj=null;
//永远返回null
pf.get();
//返回是与否从内存中有日后删除
pf.isEnQueued(); 

幻象引用的get辦法 永远返回null,主要用于检查对象是与与否日后从内存中删除。

5.生存还是死亡

通过上边对这人引用类型的分析,你有日后发现某些对象即使不可达,但也何必 是“非死不可”的,这人日后它们暂时地处“缓刑”阶段,要真正宣告另另俩个 对象死亡,大约要经历两次标记过程有日后对象在进行可达性分析后发现没有与GC Roots相连接的引用链,那它有日后被第一次标记有日后进行一次筛选,筛选的条件是此对象是与与否必要执行finalize()辦法 。当对象没有覆盖finalize()辦法 ,有日后finalize()辦法 有日后被虚拟机调用过,虚拟机将这这人清况 都视为“没有必要执行”。

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

任何另另俩个 对象的finalize()辦法 都只会被系统自动调用一次,有日后对象面临下一次回收,它的finalize()辦法 不让被再次执行。

6.总结

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

所有引用类型有的是抽象类java.lang.ref.Reference的子类,子类里提供了get()辦法 。通过上边的分析中还都可不都可不可以得知,除了幻象引用(有日后get永远返回null),有日后对象还没有被销毁,都还都可不都可不可以通过get辦法 获取原有对象。着实有个非常关键的注意点,利用软引用和弱引用,让我们歌词 都都 还都可不都可不可以将访问到的对象,重新指向强引用,也某些某些我人为的改变了对象的可达性清况 。某些某些对于软引用、弱引用相似于,垃圾收集器有日后会地处二次确认的问题图片,以确保地处弱引用清况 的对象没有改变为强引用。

有日后有个问题图片,有日后让我们歌词 都都 错误的保持了强引用(比如,赋值给了static变量),没有对象有日后就没有有日后变回相似于弱引用的可达性清况 了,就会产生内存泄露。某些某些,检查弱引用指向对象是与否被垃圾收集,也是诊断是与与否特定内存泄露的另另俩个 思路,让我们歌词 都都 的框架使用到弱引用又怀疑有内存泄露,就还都可不都可不可以从这人角度检查。

对于软引用、弱引用、幻象引用还都可不都可不可以配合引用队列(ReferenceQueue)来使用,很重是幻象引用,get辦法 只返回null,有日后再不指定引用队列,基本就没有任何意义了。

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

热门阅读:

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

参考

《深入理解Java虚拟机》

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