JVM系列之三 再谈引用

前言

上篇文章已经介绍了JVM的垃圾回收算法与收集器的实现,垃圾回收算法的基石是引用可达性分析,引用的概念就显得尤为重要,本文就再谈一谈引用。

一、引用是什么?

Java中的引用相当于C++语言中的指针,通过指针/引用可以定位到另一块内存地址中保存的数据,两者的不同点在于C++语言中的指针分配的内存需要程序员编码回收,而Java中的引用则是 “自动” 回收内存。

对于JVM的垃圾回收算法而言,引用的类型决定着被引用的对象的生命周期。

二、引用的类型

引用的类型按引用从强到弱排序包含:强引用(“Strong” Reference)、软引用(SoftReference)、弱引用(WeakReference)、虚引用(PhantomReference),对应 Java API 文档中的 java.lang.ref 包中。

强、弱、软引用类型之间是可以直接进行转换的,这几种引用不在指向任何对象,并且在 finalize 方法执行后会转换成虚引用,最后被回收。

1、强引用(“Strong” Reference)

强引用就是最常见通过 new 关键字创建返回的引用,只要强引用指向着对象,那么垃圾收集器就不会回收此对象。

只有显示地将引用赋值为 null 或超过作用域,才能被垃圾回收器收集,回收时机要与具体的回收策略有关。

2、软引用(SoftReference)

软引用相较强引用弱一些,当JVM认为堆内存不足时,垃圾收集器确保在抛出OutOfMemoryError 前,清理软引用指向的对象。

软引用通常用于实现内存敏感的缓存,当内存足够时,可保留缓存;当内存不足时,及时清理缓存,以免耗尽内存。

3、弱引用(WeakReference)

弱引用比软引用还要弱,提供非强制的映射关系,会被 JVM 择机清理。

比如维护一个对象,如果取得到就使用,取不到就重新实例化。相比软引用实现的缓存更不容易出现 OutOfMemoryError,常常出现在各大流行框架中作缓存实现。

4、虚引用(PhantomReference)

虚引用又称幻象引用,是引用类型中最弱的一种,何时被 JVM 回收也不确定,甚至于通过虚引用无法获取引用的对象。

只用于确保在 finalize方法执行后做一些后续操作,如清理等。

三、引用的可达性

对应不同引用的强弱,可以分为 强可达软可达弱可达虚可达,除此之外还有不可达 五种可达性级别(reachability level)。

1、强可达(Strongly Reachable)

强引用对应的可达性级别,由一个或多个线程通过强引用访问得到。通常来说一个线程创建了强引用对象,那么这个线程对这个对象就是强可达。

2、软可达(Softly Reachable)

软引用对应的可达性级别,即只能通过软引用获取对象时。

3、弱可达(Weakly Reachable)

弱引用对应的可达性级别,无法强引用、软引用访问,只能通过弱引用访问的对象,可达性级别为弱可达。是最接近 finalize 方法执行前的可达性级别。

4、虚可达(Phantom Reachable)

虚引用(幻象引用)对应的可达性级别,没有强引用、软引用、弱引用关联的对象,经过 finalize 后,只有虚引用引用的对象,可达性级别为虚引用。

5、不可达(unreachable)

没有任何引用关联的对象,可达性级别为不可达,可直接被垃圾收集器清理。

总结

通过对引用可达性分析,垃圾收集器可以在合适的时机回收一些不是很紧要的对象,防止内存了溢出的出现。

关于引用类型,总结如下:

  1. 强引用,只要对象引用可达,对象使用的内存就一直被占用。
  2. 软引用,对象使用的内存一直占用,直到 JVM 认为有必要回收内存。
  3. 弱引用,对象使用的内存一直占用,直到下一次 GC。
  4. 虚引用,执行 get 方法永远返回空,可以在 finalize 方法执行后做一些操作。

同步更新于本人CSDN

posted @ 2021-02-18 09:40  东北小狐狸  阅读(97)  评论(0编辑  收藏  举报