JVM | 垃圾回收策略(二)

438 阅读2分钟

这是我参与8月更文挑战的第20天,活动详情查看:8月更文挑战

本文承接上篇文章《JVM | 垃圾回收策略(一)》,继续讲JVM对象的回收策略。

三、对象回收策略

3.1 引用计数法

通过对象的引用计数器来判断该对象是否被引用。比如对于一个对象ObjectA,如果有其它对象ObjectB引用它,那么ObjectA的引用计数器就会加1,当ObjectB不再引用ObjectA,那么ObjectA的引用计数器又会减去1。

如果ObjectA的引用计数器变为0,那么说明没有任何对象在引用它,便会触发回收机制。下图展示正常的引用计数过程。

image.png

使用引用计数法去判断一个对象是否需要回收效率是挺高的,但有一个比较极端的情况,如果对象之间存在循环引用,即对象ObjectA引用ObjectB,ObjectB引用ObjectC,ObjectC引用ObjectA,如下图所示,这样的场景,引用计数法就无能为力了。会有人问,怎么会出现这样的情况呢?我们假设存在一个对象O4曾经引用了O1,后面O4取消了对O1的引用,本来O1、O2、O3都应该被垃圾回收,由于它们相互循环引用,所以根本各自的引用计数值无法达到0,即无法被回收。

image.png

需要注意的是,Java并没有采用引用计数法去判断对象是否需要回收,它采用的是可达性分析。

3.2 可达性分析

可达性分析的解决思路是,以根对象(GC Roots) 作为起点向下搜索,走过的路径被称为引用链(Reference Chain) 。如果某个对象没有任何路径链接到根对象,那么就判定这个对象是不可达的,即可以进行回收。

image.png

如图上所示,Object【1-5】是有路径链接到根对象,所以不可被回收。而Object【6-9】是没有任何路径链接到根对象,所以可被回收。

GC Roots包含的对象

  • 方法区中常量引用的对象

  • 方法区中类静态属性引用的对象

  • 本地方法栈中JNI(即Native方法)引用的对象

  • 虚拟机栈中引用的对象,一般就是我们在方法中的局部变量。


没看够,请跳转到下一篇文章JVM | 垃圾回收策略(三)