zoukankan      html  css  js  c++  java
  • 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模式的区别

  • 相关阅读:
    spark 读取mongodb失败,报executor time out 和GC overhead limit exceeded 异常
    在zepplin 使用spark sql 查询mongodb的数据
    Unable to query from Mongodb from Zeppelin using spark
    spark 与zepplin 版本兼容
    kafka 新旧消费者的区别
    kafka 新生产者发送消息流程
    spark ui acl 不生效的问题分析
    python中if __name__ == '__main__': 的解析
    深入C++的new
    NSSplitView
  • 原文地址:https://www.cnblogs.com/mzzcy/p/7043973.html
Copyright © 2011-2022 走看看