常见的GC算法介绍

x33g5p2x  于11个月前 转载在 其他  
字(2.0k)|赞(0)|评价(0)|浏览(85)

本文涵盖几种常用的垃圾回收算法的简单介绍,包括:

  • 标记清除算法(Mark-Sweep)
  • 复制算法(Copying)
  • 标记压缩算法(Mark-Compact)
  • 分代算法(GenerationalCollecting)
  • 分区算法(Region)

内容和截图全部来自《实战Java虚拟机:JVM故障诊断与性能优化(第2版)》

标记清除算法(Mark-Sweep)

标记清除法是现代垃圾回收算法的思想基础。标记清除法将垃圾回收分为两个阶段:标记阶段和清除阶段。

在标记阶段,首先通过根节点标记所有从根节点开始的可达对象。因此,未被标记的对象就是未被引用的垃圾对象。然后,在清除阶段,清除所有未被标记的对象。标记清除法的最大问题是可能产生空间碎片。

复制算法(Copying)

复制算法的核心思想是:将原有的内存空间分为两块,每次只使用其中一块,在进行垃圾回收时,将正在使用的内存中的存活对象复制到未使用的内存块中,之后清除正在使用的内存块中的所有对象,交换两个内存的角色,完成垃圾回收。

如果系统中的垃圾对象很多,复制算法需要复制的存活对象数量就会相对较少。因此,在真正需要垃圾回收的时刻,复制算法的效率是很高的。

又由于对象是在垃圾回收过程中统一被复制到新的内存空间中的,可确保回收后的内存空间是没有碎片的。虽然有以上两大优点,但是复制算法的代价却是将系统内存折半,因此,单纯的复制算法也很难让人接受。

改进的复制算法

在Java的新生代SerialGC回收器中,使用了复制算法的思想。新生代分为eden区、from区和to区3个部分。其中from区和to区可以视为用于复制的两块大小相同、地位相等且可进行角色互换的空间。from区和to区也称为survivor区,即幸存者空间,用于存放未被回收的对象。

在进行垃圾回收时,eden区的存活对象会被复制到未使用的survivor区(假设是to区),正在使用的survivor区(假设是from)的年轻对象也会被复制到to区(大对象或者老年对象会直接进入老年代,如果to区已满,则对象也会直接进入老年代)。此时,eden区和from区的剩余对象就是垃圾对象,可以直接清空,to区则存放此次回收后的存活对象。这种改进的复制算法,既保证了空间的连续性,又避免了大量的内存空间浪费,如下图所示。

标记压缩算法(Mark-Compact)

标记压缩法是一种老年代的回收算法。它在标记清除法的基础上做了一些优化。和标记清除法一样,标记压缩法首先也需要从根节点开始,对所有可达对象做一次标记。但之后,它并不只是简单地清理未标记的对象,而是将所有的存活对象压缩到内存的一端。然后,清理边界外所有的空间。这种方法既避免了碎片的产生,又不需要两块相同的内存空间,性价比较高。

分代算法(GenerationalCollecting)

由于新生代和老年代的特点不一样,所以针对不同的代使用不同的算法。

新生代一般使用复制算法,例如以下的垃圾收集器就是基于复制算法的:

  • SerialGC
  • ParNewGC
  • ParallelGC

而老年代一般使用标记清除或标记压缩算法,例如以下的垃圾收集器:

  • CMS
  • ParallelOldGC

分区算法

分区算法将整个堆空间划分成连续的不同小区间,如下图所示。每一个小区间都独立使用,独立回收。这种算法的好处是可以控制一次回收小区间的数量。

一般来说,在相同条件下,堆空间越大,一次GC所需要的时间就越长,从而产生的停顿也越长。为了更好地控制GC产生的停顿时间,将一块大的内存区域分割成多个小块,根据目标停顿时间,每次合理地回收若干个小区间,而不是回收整个堆空间,从而减少一次GC所产生的停顿。

G1收集器简介

G1回收器(GarbageFirst)是在JDK1.7中正式使用的全新的垃圾回收器,从长期目标来看,它是为了取代CMS回收器。G1回收器拥有独特的垃圾回收策略,和之前提到的回收器截然不同。

从分代上看,G1依然属于分代垃圾回收器,它会区分年轻代和老年代,依然有eden区和survivor区,但从堆的结构上看,它并不要求整个eden区、年轻代或者老年代都连续。

它使用了分区算法。作为CMS的长期替代方案,G1使用了全新的分区算法,其特点如下:

  • 并行性:G1在回收期间,可以由多个GC线程同时工作,有效利用多核计算能力。
  • 并发性:G1拥有与应用程序交替执行的能力,部分工作可以和应用程序同时执行,一般来说,不会在整个回收期间完全阻塞应用程序。·
  • 分代GC:G1依然是一个分代回收器,但是和之前的回收器不同,它同时兼顾年轻代和老年代,其他回收器或者工作在年轻代,或者工作在老年代。·
  • 空间整理:G1在回收过程中,会进行适当的对象移动,不像CMS,只是简单地标记清理对象,在若干次GC后,CMS必须进行一次碎片整理。而G1不同,它每次回收都会有效地复制对象,减少碎片空间。·
  • 可预见性:由于分区的原因,G1可以只选取部分区域进行内存回收,这样缩小了回收的范围,全局停顿也能得到较好的控制。

相关文章