JVM垃圾回收算法 及 垃圾收集器

摘自《深入理解Java虚拟机》

一、什么是:

  GC算法是 方法论,那么垃圾收集器就是具体的 实现

二、四种 垃圾回收算法

  1、标记-清除算法:最基础的收集算法;不足有两点:1标记和清除两个过程效率都不高;2会产生空间碎片;

  2、复制算法:实现简单,效率较高;不足是空间利用率底,只得意了一半的空间。

         HotSpot中新生代主要也是 复制算法,但不是按1:1来划分空间,而是划分为Eden和两个Survivor空间,默认是8:1,也就是新生代能利用 90%空间;当Survivor空间不足时,需要依赖老年代分配担保。

  3、标记-整理算法:主要用在老年代中;和标记-清除不同的是,它先标记,再移动,再清除边界外的空间;

  4、分代收集算法:现在商业虚拟机主要的收集算法,是把堆分为新生代和老年代,然后分别采用上面3种算法;主要是新生代用复制算法,老年代用标记-清除 或 标记-整理算法;

三、7 种收集器:

  JDK 1.7 update 14 HotSpot虚拟机垃圾收集器;

  

  tenured generation(老年代);

  连线的收集器表示可搭配使用,共7种作用于不同分代的收集器。

  下面主要从三个方面总结,特性、原理、应用;

  1. Serial

    a. 最基本、历史最悠久;简单高效;

    b. 单线程收集器;在它进行垃圾收集时,必须暂停其它所有的工作线程(STOP THE WORLD),直到它收集结束;采用复制算法回收;

    d. Client模式默认的 新生代 收集器,是Client不错的选择。

  2. Serial Old

    a. 同Serial收集器;

      b. 使用 标记-整理 算法;

    c. 主要用在Client模式的 老年代,和Serial搭配使用;

      也可用在Server模式下:1是在JDK 1.6前与Parallel Scavenge搭配;2使用CMS的后备方案,在CMS 并发收集发生 Concurrent Mode Failure时使用;

    

  3. ParNew

    a. 简单高效;其实就是Serial收集器的多线程版本,两者共用了相当多的代码;

    b. 并行多线程;采用复制算法

    c. 在Server模式下首选的收集器;除了Serial外,目前只有它能与CMS搭配使用(主要也是和CMS搭配);

  4. Parallel Scavenge

    a. 和ParNew类似;使GC尽的吞吐量可控,使之高效率使用CPU,尽快完成运算任务;可打开“自适应调节”策略,使之自动配置虚拟机各项参数。

      关注点和其它收集器不太一样,CMS等收集器关注的是缩短用户线程的停顿时间,但多花费时间多于Parallel Scavenge;

      吞吐量 =  运行用户代码时间 / (运行用户代码时间 + 垃圾收集时间);如虚拟机部花费100分钟,其中垃圾收集花费1分钟,那吞吐量即99%;

    b. 并行多线程;采用复制算法

    c. 主要用在 后台运算 任务 不需要太多交互 上。

  5. Parallel Old

    a. 由于老年代的Serial Old在服务端应用性能上的“拖累”,它主要为了和 Parallel Scavenge 搭配;JDK 1.6才开始有;

    b. 采用 标记-整理

    c. 主要用在服务模式下,和 Parallel Scavenge 搭配;

    

  6. CMS(Concurrent Mark Sweep)

    a. 强交互,具有划时代意义;真正意义上的并发收集器;

    b. 主要四个步骤:

       1. 初始化标记 initial mark (STW)

       2. 并发标记 concurrent mark

       3. 重新标记 remark (STW)

       4. 并发清除 concurrent sweep

      其中 初始化 和 重新标记 都会STW,重新标记停顿时间长于初始化标记,但两者的总共停顿时间都很短。大部分时间都花在并发标记和并发清除上。

     使用 标记-清除 算法,会产生空间碎片;当老年代空间不够分配时,在触发一次FullGC前会进行碎片的合并和整理。

     CMS主要是在并发环境下进行,所以它不能像其它收集器那样等到老年代用完了再GC,它需要预留一部分空间给并发收集线程使用,它可以设定一个阈值。如果预留的空间也不够收集线程使用,就会出现一次 ConcurrentModeFailure,这时会启用后备方案Serial Old方案来清理,这样也会带来STW,停顿时间就会变长。

    c. 通常和 ParNew搭配运行在服务端,也是现在用服务端主流的收集器。

    

  7. G1(Garbage-First)

      a. JDK 1.7正式使用,最新的的技术实现;高并发,主要面向服务端;不需要和其它收集器搭配;

      b. 主要四个步骤:

       1. 初始化标记 initial mark (STW)

       2. 并发标记 concurrent mark

       3. 最终标记 remark (STW)

       4. 筛选回收 concurrent sweep(可并,可停顿,停顿不会太长且效率更高)

       整体上是 标记-整理 算法,但局部两个Region之间是复制算法

       其它收集器都是针对整个新生代 或 整个老年代的收集,而G1可对Region进行分隔收集,通过计算每个Region可回收的空间大小,维护一个优先列表,回收时优先回收空间较大的(这也是Garbage-Firsst的由来),这样也可实现用户定义的时间内完成收集。

      c. 现在在实践生产中还应用得不多,只是它已是一种技术驱向;

    

三、其它点:

  1、垃圾回收中的 并行(Parallel)与 并发(Concurrent):

    并行:多个回收线程在多个CPU上一起执行回收操作;会STOP THE WORLD;

    并发:回收线程和其它任务线程并发执行(不一定就是并行,可能会交替执行)工作;不会STOP THE WORLD,用户感觉不到停顿;

扩展阅读:

  深入理解Major GC, Full GC, CMS

  JVM client模式和Server模式的区别

原文地址:https://www.cnblogs.com/mzzcy/p/7043973.html