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

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