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

  • 时间:
  • 浏览:1
  • 来源:大发pk10_pk10开户_大发pk10开户

关于强引用、软引用、弱引用、幻象引用的区别,在太多太多公司的面试题中总是 出现,肯能某些小伙伴随便说说你你这些知识点比较冷门,但随便说说让让这么 人都有开发中总是 用到,如new另1个多 对象的后来本来强引用的应用。

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

你这些种生活应用主要的区别体现在对象不同的可达性请况和对垃圾分派的影响,让让这么 人都之间的可达性请况时需参看下图:

1.强引用(strong reference)

强引用本来让让这么 人都最常见的普通对象引用(如new 另1个多 对象),倘若还有强引用指向另1个多 对象,就表明此对象还“活着”。在强引用背后,即使JVM内存空间严重不足,JVM宁愿抛出OutOfMemoryError运行时错误(OOM),让应用多多线程 异常终止,本来会靠回收强引用对象来防止内存严重不足的那些的问题报告 。对于另1个多 普通的对象,肯能不也能 某些的引用关系,倘若超过了引用的作用域肯能显式地将相应(强)引用赋值为null,就意味着着分析分析此对象时需被垃圾分派了。但要注意的是,并一定会赋值为null后就立马被垃圾回收,具体的回收时机还是要看垃圾分派策略的。

如Object obj = new Object();

2.软引用(soft reference)

软引用相对强引用要弱化某些,时需让对象豁免某些垃圾分派。当内存空间足够的后来,垃圾回收器不需要回收它。不也能当JVM认定内存空间严重不足时才会去回收软引用指向的对象。JVM会确保在抛出OOM前清理软引用指向的对象,后来JVM是很聪明的,会尽肯能优先回收长时间闲置不需要的软引用指向的对象,对那些刚构建的或刚使用过的软引用指向的对象尽肯能的保留。基于软引用的那些型态,软引用时需用来实现太多太多内存敏感点的缓存场景,即肯能内存还有空闲,时需暂时缓存某些业务场景所需的数据,当内存严重不足时就时需清理掉,等底下再时需时,时需重新获取并再次缓存。原来就确保在使用缓存提升性能的一起去,不需要意味着着分析耗尽内存。

软引用通常时需和另1个多 引用队列(ReferenceQueue)联合使用,肯能弱引用所引用的对象被垃圾回收,java虚拟机就会把你你这些软引用加入到与之关联的引用队列中。

Object obj = new Object();
SoftReference<Object> sf = new SoftReference<Object>(obj);
obj = null;
//有后来会返回null
sf.get(); 

通过底下的代码时需看出sf是对obj的另1个多 软引用,当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)

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

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

幻象引用的get依据永远返回null,主要用于检查对象是是不是肯能从内存中删除。

5.生存还是死亡

通过底下对并是不是生活引用类型的分析,你肯能发现某些对象即使不可达,但太多太多须是“非死不可”的,你你这些后来它们暂时存在“缓刑”阶段,要真正表态另1个多 对象死亡,为宜要经历两次标记过程肯能对象在进行可达性分析后发现不也能 与GC Roots相连接的引用链,那它肯能被第一次标记后来进行一次筛选,筛选的条件是此对象是是是不是必要执行finalize()依据。当对象不也能 覆盖finalize()依据,肯能finalize()依据肯能被虚拟机调用过,虚拟机将你这些种生活请况都视为“不也能 必要执行”。

肯能你你这些对象被判定为有必要执行finalize()依据,不也能 你你这些对象肯能放置在另1个多 叫做F-Queue的队列之中,并在稍后被另1个多 由虚拟机自动建立的、低优先级的Finalizer应用多多线程 去执行它。这里所谓的“执行”是指虚拟肯能触发你你这些依据,但不须承诺会等待的图片 它运行后来开始了,原来做的意味着着分析是,肯能另1个多 对象在finalize()依据中执行缓慢,肯能存在了死循环(更极端的请况),将很肯能会意味着着分析F-Queue队列中某些对象永久存在等待的图片 ,甚至意味着着分析整个内存回收系统奔溃。finalize()依据是对象逃脱死亡命运的最后一次肯能,稍后GC将对F-Queue中的对象进行第二次小规模的标记,肯能对象要在finalize()中成功拯救某些人——倘若重新与引用链上的任何另1个多 对象建立关联即可。譬如把某些人(this关键字)赋值给某个类变量肯能对象的成员变量,那在第二次标记时它将被移除出“即将回收”的集合;肯能对象这后来还不也能 逃脱,那基本上它就真的被回收了。

任何另1个多 对象的finalize()依据都只会被系统自动调用一次,肯能对象面临下一次回收,它的finalize()依据不需要被再次执行。

6.总结

对象的可达性是JVM垃圾分派器决定怎样才能防止对象的另1个多 重要考虑指标

所有引用类型一定会抽象类java.lang.ref.Reference的子类,子类里提供了get()依据。通过底下的分析中时需得知,除了幻象引用(肯能get永远返回null),肯能对象还不也能 被销毁,时需通过get依据获取原有对象。随便说说有个非常关键的注意点,利用软引用和弱引用,让让这么 人时需将访问到的对象,重新指向强引用,也本来人为的改变了对象的可达性请况。太多太多对于软引用、弱引用同类,垃圾分派器肯能会存在二次确认的那些的问题报告 ,以确保存在弱引用请况的对象不也能 改变为强引用。

后来有个那些的问题报告 ,肯能让让这么 人都错误的保持了强引用(比如,赋值给了static变量),不也能 对象肯能就不也能 肯能变回同类弱引用的可达性请况了,就会产生内存泄露。太多太多,检查弱引用指向对象是是不是被垃圾分派,也是诊断是是是不是特定内存泄露的另1个多 思路,让让这么 人都的框架使用到弱引用又怀疑有内存泄露,就时需从你你这些宽度检查。

对于软引用、弱引用、幻象引用时需配合引用队列(ReferenceQueue)来使用,特别是幻象引用,get依据只返回null,肯能再不指定引用队列,基本就不也能 任何意义了。

底下分析了并是不是生活引用类型的使用,熟悉这几种应用类型对深入理解JVM也大有裨益。

热门阅读:

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

参考

《深入理解Java虚拟机》

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