Java中的强引用、软引用、弱引用、幻象引用及其区别

文章目录

    • 引用的特征介绍
            • 强引用(Strong Reference)
            • 软引用(Soft Reference)
            • 弱引用(Weak Reference)
            • 幻想引用(虚引用)
    • 对象可达性状态流转分析
      • 人为改变对象可达性状态

在java语言中,除了基本数据类型的变量,其他所有都是所谓的引用类型。它们执行不同的对象,理解引用对掌握Java的生命周期和JVM内部相关机制非常有帮助

不同的引用类型, 主要体现的是对象不同的可达性和对垃圾收集的影响。

引用的特征介绍

强引用(Strong Reference)
就是最常见的普通对象引用,我们平常典型编码Object obj = new Object()中的obj就是强引用。通过关键字new
创建的对象所关联的引用就是强引用
只要这个强引用还指向着某一对象,那就说明这个对象还“活着”,垃圾收集器就不会碰,当JVM内存空间不足,JVM宁愿
抛出OutOfMemoryError运行时错误(OOM),使程序异常终止,也不会靠随意回收具有强引用的“存活”对象来解决内
存不足的问题。
对于一个普通的对象,如果没有其他的引用关系,只要超出了引用的作用域或显示的将(强)引用赋值
为null,就是可以被垃圾收集的了。当然具体的回收时机还得看垃圾收集策略。
软引用(Soft Reference)
从名字可以看出,这是一种相对于强引用更弱化的一种引用,它可以让所指对象豁免一下垃圾收集,只有当JVM认为
内存不足时,才会去尝试回收软引用所指的对象。JVM会确保在抛出 OutOfMemoryError 之前,清理软引用所指
对象。软引用通常用来实现内存敏感的缓存,如果还有空闲的内存,就可以暂时保留缓存,当内存不足时就清理掉,
这样就保证了使用了缓存的同时,又不会耗尽内存。
弱引用(Weak Reference)
这种引用并不会让所指对象豁免垃圾回收,仅仅是提供一种访问在弱引用状态下的对象的途径。这就可以用来构建一
种没有特定约束的关系,,比如,维护一种非强制性的映射关系,如果试图获取对象时,对象还在,就使用它,否则
就重新实例化。它同样是很多缓存的选择。
幻想引用(虚引用)
不能通过它来访问对象, 幻想引用仅仅是提供了一种确保对象被 finalize 以后,做某些事情的机制。,比如,通
常用来做所谓的 Post-Mortem 清理机制, Java 平台自身 Cleaner 机制等,也有人利用幻想引用监控对象的创建和销毁。

对象可达性状态流转分析

下面这张图总结了对象的生命周期和不同的可达性状态,以及不同状态可能改变的关系。
Java中的强引用、软引用、弱引用、幻象引用及其区别_第1张图片

  1. 强可达(Strongly Reachable):就是当一个对象可以有一个或多个线程通过不同的引用访问到的情况。比如,新创建的一个对象,那么创建它的线程对这个对象就是强可达。

  2. 软可达(Softly Reachable):只有我们通过软引用才能访问到对象的状态。

  3. 弱可达(Weakly Reachable):无法通过强引用或软引用访问,只能通过弱引用才能访问的状态。这是十分临近 finalize 状态的时机,当弱引用被清除时,就符合 finalize 的条件了。

  4. 幻象可达(Phantom Reachable):就是没有强、软、弱引用关联,并且 finalize 过了,只有幻象引用指向这个对象的时候。

  5. 不可达(unreachable):意味着对象可以被清除了。

判断对象可达性,是 JVM 垃圾收集器决定如何处理对象的一部分考虑。

人为改变对象可达性状态

所有引用类型,都是抽象类 java.lang.ref.Reference 的子类,它提供了 get() 方法:
在这里插入图片描述
除了幻象引用(因为 get 永远返回 null),如果对象还没有被销毁,都可以通过 get 方法获取原有对象。这意味着,利用软引用和弱引用,我们可以将访问到的对象,重新指向强引用,也就是人为的改变了对象的可达性状态!这也是为什么在上面图里有些地方画了双向箭头。

所以,对于软引用、弱引用之类,垃圾收集器可能会存在二次确认的问题,以保证处于弱引用状态的对象,没有改变为强引用。

你可能感兴趣的:(Java)