JVM - GC

Q:如何确认那些对象的可以回收的

  1. 引用计数

    “jvm引用计数”的图片搜索结果

    如上图,左边为堆,右边为虚拟机栈中的局部变量表,如果堆中的对象相互引用了,那么使用这种方式,即使将引用1跟2断开,对象的引用数量不为0,此时两个堆中的对象无法回收,所以现有的主流jvm虚拟机实现基本不会采用这种方式。

  2. GCRoot(可达性分析)

    从如下的GCRoot节点开始向下搜索,当一个对象跟GCRoot节点没有任何引用链的时候,这个对象就是可以回收的。

可以作为GCRoot的有

  • 虚拟机栈中的局部变量表中的引用
  • 本地方法栈。。
  • 方法区中类静态变量引用的对象
  • 方法区中常量引用的对象

Q:怎么回收

  1. 标记-清除:通过GCRoot找到可回收对象,标记之后清除掉。

    会有空间碎片

  2. 标记-整理:找到可回收对象之后将它拼接到内存空间的首部

  3. 复制:将空间分为两部分A跟B,当A需要回收时,将不回收的对象copy到B,之后清除A。

    空间浪费

  4. 分代算法:将堆空间分为新生代跟老年代,新生代中的对象在GC的时候有很大一部分需要被回收(IBM-98%),对新生代的GC我们可以改进下复制算法,将区域分为eden(80%)跟两个survivor A跟B(20%);申请空间的时候我们从优先从eden申请,之后从A申请,回收的时候将eden跟A中的不回收对象copy到B,之后清理掉eden跟A。如此。。

    对于老年代,每次GC都会有很大部分对象不需要被回收掉,所以更加适合标记-整理算法。