这是我参与8月更文挑战的第20天,活动详情查看:8月更文挑战
本文承接上篇文章《JVM | 垃圾回收策略(一)》,继续讲JVM对象的回收策略。
三、对象回收策略
3.1 引用计数法
通过对象的引用计数器来判断该对象是否被引用。比如对于一个对象ObjectA,如果有其它对象ObjectB引用它,那么ObjectA的引用计数器就会加1,当ObjectB不再引用ObjectA,那么ObjectA的引用计数器又会减去1。
如果ObjectA的引用计数器变为0,那么说明没有任何对象在引用它,便会触发回收机制。下图展示正常的引用计数过程。
使用引用计数法去判断一个对象是否需要回收效率是挺高的,但有一个比较极端的情况,如果对象之间存在循环引用,即对象ObjectA引用ObjectB,ObjectB引用ObjectC,ObjectC引用ObjectA,如下图所示,这样的场景,引用计数法就无能为力了。会有人问,怎么会出现这样的情况呢?我们假设存在一个对象O4曾经引用了O1,后面O4取消了对O1的引用,本来O1、O2、O3都应该被垃圾回收,由于它们相互循环引用,所以根本各自的引用计数值无法达到0,即无法被回收。
需要注意的是,Java
并没有采用引用计数法去判断对象是否需要回收,它采用的是可达性分析。
3.2 可达性分析
可达性分析的解决思路是,以根对象(GC Roots) 作为起点向下搜索,走过的路径被称为引用链(Reference Chain) 。如果某个对象没有任何路径链接到根对象,那么就判定这个对象是不可达的,即可以进行回收。
如图上所示,Object【1-5】是有路径链接到根对象,所以不可被回收。而Object【6-9】是没有任何路径链接到根对象,所以可被回收。
GC Roots包含的对象
-
方法区中常量引用的对象
-
方法区中类静态属性引用的对象
-
本地方法栈中JNI(即Native方法)引用的对象
-
虚拟机栈中引用的对象,一般就是我们在方法中的局部变量。
没看够,请跳转到下一篇文章JVM | 垃圾回收策略(三)