Java对象活着判断

简介

JVM 堆里面存放着 Java 世界中几乎所有的对象实例,在垃圾收集器对堆进行垃圾回收的时候,哪些对象该回收,哪些对象该保留成了一个比较头疼的问题。判断对象能不能回收就有两种算法:

  1. 引用计数算法。

  2. 可达性分析算法。

引用计数算法

引用计数算法就是在对象里面加一个引用计数器。什么叫引用计数器呢?就是定义一个被引用的变量,当有对象引用它的时候,就将该变量加 1,不引用的时候,就将该变量减 1。当该对象的引用计数器为 0 的时候,就表示没有被任何对象引用。就可以被回收。

但是这样存在一个问题,就是循环依赖的问题,比如 A 类里面引用了 B 类的一个对象,而 B 类引用了一个 A 类的对象,这样这两个类循环依赖,但是没有其它作用,就不会被回收,这样就会一直存在堆中,占用内存。该方法效率比较高,比较容易理解,但是垃圾回收器没有使用该算法。

可达性分析算法

通过定义一系列根对象作为起点,向下寻找,所经历过的路径就叫做引用链,被引用链链接着的对象就是活着的对象,那些没有被这些根对象引用着的对象,就是不存活对象,这些对象就会被回收。详见下图:

01_可达性判断是否可以回收.png

Java中引用方式扩充

在 Java 中,对象存在引用和没有引用两种状态,Java 中通过一些操作可以当内存空间还很充足的时候,就将对象保留在内存中,如果内存空间不够了,就将对象作为垃圾对象回收。

Java 在这方面设计添加了强引用(Strong Reference)、软引用(Soft Reference)、弱引用(Weak Reference)和虚引用(Phantom Reference)。

强引用

代码中普遍存在的引用就是强引用,给一个变量等于号赋值。只要强引用存在,垃圾收集器就永远不能够回收被引用的对象。

软引用

软引用表示一些有用的但是不一定必须要的对象。当要发生垃圾回收的时候,jvm中内存不足的时候,会对软引用的对象进行回收。

弱引用

当发生垃圾回收的时候,无论 JVM 的内存足够还是不足够,都会将弱引用的对象进行回收。

虚引用

它是最弱的引用关系,一个对象是否有虚引用的存在,完全不会对其生存时间构成影响,不能够通过虚引用来产生一个对象实例。在垃圾回收的时候,随时都可以回收虚引用的对象。