JVM垃圾回收

回收方法

  1. 引用计数算法:
    给对象中添加一个引用计数器,每当有一个地方引用它时,计数器+1,当引用失效,计数器-1.任何时刻计数器为0的对象就是不可能再被使用的。
  • 优点:实现简单,判定效率高效,被actionscript3和python中广泛应用。
  • 缺点:无法解决对象之间的相互引用问题。java没有采纳
  1. 可达性分析算法:

通过一系列称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GCRoots没有任何引用链相连的时候,则证明此对象是不可用的。
比如如下,右侧的对象是到GCRoot时不可达的,可以判定为可回收对象。


JVM垃圾回收_第1张图片
image.png

回收依据

在java中,可以作为GCRoot的对象包括以下几种:

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

那么是不是这些对象就非死不可,也不一定,此时只能宣判它们存在于一种“缓刑”的阶段,要真正的宣告一个对象死亡。至少要经历两次标记:第一次:对象可达性分析之后,发现没有与GCRoots相连接,此时会被第一次标记并筛选。第二次:对象没有覆盖finalize()方法,或者finalize()方法已经被虚拟机调用过,此时会被认定为没必要执行。

如何回收

  1. 标记清除法(Mark-Sweep)
    标记清除法是垃圾回收算法的思想基础。标记清除算法将垃圾分为两个阶段:标记阶段和清除阶段。
    标记阶段,通过根节点,标记所有从根节点开始的可达对象,未标记过的对象就是未被引用的垃圾对象。
    清除阶段,清除所有未被标记的对象。


    JVM垃圾回收_第2张图片
    image.png
  1. 复制算法(Copying)
    复制算法是,将原有的内存空间分为两块,每次只使用其中一块,在垃圾回收时,将正在适用的内存中存活对象复制到未使用的内存块,然后清除使用的内存块中所有的对象。


    JVM垃圾回收_第3张图片
    image.png
  1. 标记压缩算法(Mark-Compact)
    标记压缩算法是一种老年代的回收算法。
    标记阶段和标记清除算法一致,对可达对象做一次标记。
    清理阶段,为了避免内存碎片产生,将所有的存活对象压缩到内存的一端。


    JVM垃圾回收_第4张图片
    image.png
  1. 分代收集算法
    GC分代的基本假设:绝大部分对象的生命周期都非常短暂,存活时间短。
    “分代收集”(Generational Collection)算法,把Java堆分为新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法。在新生代中,每次垃圾收集时都发现有大批对象死去,只有少量存活,那就选用复制算法,只需要付出少量存活对象的复制成本就可以完成收集。而老年代中因为对象存活率高、没有额外空间对它进行分配担保,就必须使用“标记-清理”或“标记-整理”算法来进行回收。

你可能感兴趣的:(JVM垃圾回收)