一、垃圾回收总览
二、判定垃圾对象之引用计数法
- 引用计数器算法算是一种古老的java垃圾回收算法,目前很多版本的java(jdk1.8也已废弃)已经废弃掉这种算法了。
- 定义:给每个对象分配一个计算器,当有引用指向这个对象时,计数器加1,当指向该对象的引用失效时,计数器减一。最后如果该对象的计算器为0时,java垃圾回收器会认为该对象是可回收的。
- 缺陷:
- 每次对象被引用时,都需要去更新计数器,有一点时间开销。
- 无法解决循环引用问题。
- 浪费cpu,即使内存够用,仍然在运行时进行计数器的统计
2.1 什么是循环引用问题
public class GCTest { private Object instance; public static void main(String[] args) { GCTest gc1 = new GCTest(); GCTest gc2 = new GCTest(); gc1.instance = gc2; gc2.instance = gc1; gc1 = null; gc2 = null; System.gc(); } }
- 如上述代码,在gc1 = null; gc2 = null; 这两条语句还没执行的时候,如下图,两个对象的计数器值都是2
- 但是当gc1 = null; gc2 = null; 执行后如下图,两个对象的计数器值都是1,所以对象不会被清理,但是这两个对象其实是垃圾了,这就是循环引用问题。
三、判定垃圾对象之可达性分析算法
- 这个算法的基本思路就是通过一系列的称谓“GC Roots"的对象作为起始点,从这些节点开始向下搜索,搜索所有走过的路径为引用链,当一个对象到GC Roots没有任何引用链项链时,则证明此对象时不可用的:
注:Java语言中,可作为GC Roots的对象包括下面几种:
1) 虚拟机栈(栈帧中的本地变量表)中引用的对象
2) 方法区中类静态属性引用的对象
3) 方法区中常量引用的对象
4) 本地方法栈中JNI(即一般说的Native方法)引用的对象
- 如上图,以栈中的引用为GC ROOTS,对象3和对象4随便彼此引用,但是GC ROOTS无法搜索到,所以对象3和对象4会被当成垃圾清理。