定义

Java中,一个对象的可达性(Reachable)是指从一系列GC Roots的对象出发,从这些节点往下搜索,搜索时走过的路径称为引用链(Reference Chain),当一个对象不在任何GC Roots的引用链中时,则表示此对象是不可到达的,将会被判定为可回收对象。

说明

可达性,主要是用来作为垃圾回收器回收的标准,表示一个对象可被访问的难易程度。

可达性按强弱程度依次为强可达(strongly reachable)、软可达(softly reachable)、弱可达(weakly reachable)、虚可达(phantom reachable)和不可达(unreachable)。

1
2
3
4
5
当一个对象有其它对象或变量持有其强引用时,该对象就处于强可达状态。
当一个对象没有任何对象或变量持有其强引用,但有对象或变量持有其软引用,则该变量处于软可达状态。
当一个对象既没有强引用,也没有软引用指向它,但有弱引用与其关联,则该变量处于弱可达状态。
当一个对象仅存在虚引用与其关联时,该变量处于虚可达状态。
当一个对象不存在任何引用与其关联时,该变量处于不可达状态。

垃圾回收,回收的自然是“垃圾”,那么“垃圾”的判断标准是什么?在Java中,使用的是可达性分析算法,也就是根据对象的可达性来判断它是否该被回收。当内存足够时,如果一个对象是弱可达、虚可达或者不可达的,那么它就会判定为可回收对象。如果内存不足时,那么软可达对象也会纳入回收范围之内。

GC Roots

那么什么样的对象可以作为GC Roots呢?一般来说,如下情况的对象可以作为GC Roots:

1
2
3
4
1. 虚拟机栈(栈桢中的本地变量表)中引用的对象
2. 方法区中的类静态属性引用的对象
3. 方法区中的常量引用的对象
4. 本地方法栈中JNI(Native方法)引用的对象

可达性判断

JVM在进行GC时,判断一个对象是否存在引用,是从根引用GC Roots开始去标识,到达同一个对象的路径有时可能会有多条,如下图所示:

此时,JVM判断的标准是:

  1. 如果只存在一条路径,则以该路径上最弱的引用为准。
  2. 如果存在不同路径,则以最强的路径引用为准。

例如Obj4的引用,存在3个路径:1->6、2->5、3->4, 那么从根对象到Obj4最强的引用是2->5,因为它们都是强引用,此时Obj4为强可达(strong reachable)对象。

如果仅仅存在一个路径对Obj4有引用时,比如现在只剩1->6,那么根对象到Obj4的引用就是以最弱的为准,就是SoftReference引用,Obj4就是软可达(softly-reachable)对象。

如果还想了解在HotSpot虚拟机中是如何实现可达性分析算法的话,可以点这里