深入理解JVM之GC算法(八)

概述

垃圾回收,Garbage Collection,简称GC。思考GC需要完成三件事:

  • 哪些内存需要回收?
  • 什么时候回收?
  • 如何回收?

对象存活判断

引用计数法

每个对象有一个引用计数属性,新增一个引用时计数加1,引用释放时计数减1,计数为0时可以回收。此方法简单,无法解决对象相互循环引用的问题。

可达性分析(Reachability Analysis)

从GC Roots开始向下搜索,搜索所走过的路径称为引用链。当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的。不可达对象。

在Java语言中,GC Roots包括:

  • 虚拟机栈中引用的对象。
  • 方法区中类静态属性实体引用的对象。
  • 方法区中常量引用的对象。
  • 本地方法栈中JNI引用的对象。

垃圾回收算法

标记-清除

Mark-Sweep:先标记所有需要回收的对象,然后统一回收。
之所有说它是最基础的收集算法,是因为后续的收集算法都是基于这种思路并对其不足进行改进而得到的。
不足之处:

  1. 效率问题,标记和清除两个过程的效率都不高。
  2. 空间问题,会产生大量不连续的内存碎片。分配大对象时容易提前触发GC。

复制算法

为了解除标记清除算法的效率问题,就是将内存一分为二,每次只用其中一半,等到这一块用完了,直接将存活的对象复制到另外一半,然后一次性清理已使用过的空间。
优缺点:
实现简单,分配快,只需要顺序移动堆顶指针就可以进行分配,高效。代价是内存浪费大。

标记-整理

Mark-Compact:先标记,然后将存活对象移向一边,再清理掉边界以外的内存。

分代收集

一般的虚拟机都是分代收集算法,也就是把内存分为几个块,不同的块用不同的回收算法。

一般将内存分为新生代和年老代,在新生代一般采用复制算法,年老代因为存活率高、没有多少额外空间,则必须采用标记-清理或者标记-整理算法。