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

  • 时间:
  • 浏览:0
  • 来源:极速快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