垃圾回收算法

引用计数算法

基本思路

在对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加一;当引用失效时,计数器值就减一;任何时刻,计数器值为零的对象就是不可能再被使用的。

优点/缺点

引用计数算法的原理简单,执行高效,但是主流的 Java 虚拟机中都没有选择引用计数算法来进行内存管理,主要原因是这个看似简单的算法其实有很多例外情况需要考虑,必须配合大量额外处理才能保证算法正常地工作,例如在涉及对象之间互相循环引用的问题。

经典案例

Netty 中的 ByteBuf 使用了引用计数算法,提供了优于 JVM GC 和引用队列的高效的实时性。

可达性分析

基本思路

当前主流程序语言的内存管理都是通过可达性分析(Reachability Analysis)算法来判定对象是否存活的。

通过一系列的「GC Roots」的根对象作为起始节点,从这些节点开始根据引用关系向下搜索,搜索过程所走过的路径被称为「引用链(Reference Chain)」,如果某个对象到 GC Roots 间没有任何引用链相连,或者用图论的话来说就是从 GC Roots 到这个对象不可达,则证明此对象是不可能再被使用的。

      GC Roots
-----------------------------------------------
	      |
	   object1                  object5
    /       \                /       \
object2   object3        object6   object7
             |
          object4

在 Java 技术体系中,固定可作为 GC Roots 对象包括以下几种:

  • 在虚拟机栈中引用的对象,例如各个线程被调用的方法堆栈中使用到的参数、局部变量、临时变量等;

  • 在方法区中类的静态属性引用的对象,例如 Java 类的引用类型的静态变量;

  • 在方法区中常量引用的对象,例如字符串常量池中的引用;

  • 在本地方法区中 JNI 引用的对象;

  • 在 Java 虚拟机内部的引用,例如基本数据类型对应的 Class 对象,一些常驻的异常对象,系统类加载器等;

  • 所有被同步的锁(synchronized 关键字)持有的对象;

  • JMXBean、JVMTI 中注册的回调、本地代码缓存等

  • ......

最后更新于