JVM垃圾收集器

1. Serial 新生代收集器

  1. 新生代 单线程收集器,它在进行垃圾收集时必须暂停其他所有工作的线程,造成 Stop The World。
  2. 由于Stop The World 它并不是一个很好的收集器,但是他是Client端的默认收集器,因为简单,并且桌面应用新生代内存不会太大所有停顿可以接受因此效率高。

2.ParNew 新生代收集器

  1. Serial的多线程版,是一个并行多线程收集器。和Serial有相同的收集算法,Stop The World 等等等等。
  2. 他是Server模式下首选的新生代收集器。
  3. 新时代中除Serial外只有ParNew可以和CMS收集器配合使用。
  4. 单CPU下由于线程交互开销ParNew并不比Serial好。

3. Parallel Scavenge  新生代收集器

  1. 和ParNew一样
  2. 这个新生代收集器与其他的关注点不同,其他收集器尽可能要缩短停顿时间,而他则是达到一个可以控制的吞吐量
  3. 此处吞吐量 = 运行代码时间/(运行代码时间+垃圾回收时间) 
  4. 高吞吐量可以高效利用CPU时间,主要用在没有太多交互,大量运算的任务。

4.Serial Old 老年代收集器

  1. 和Serial一样,但在老年代。
  2. 在Server端下有2大是用途。
    1. jdk1.5及以前的版本中和Parallel Scavenger 搭配使用。其实在Parallel Scavenger 收集器架构当中有PS MarkSweep 收集器来收集老年代,但是他和Serial Old非常接近,所以就认为是和Serial Old 搭配使用。
    2. 作为 CMS 后备预案,在并发收集发生Concurrent Mode Failare 时使用

5.Parallel Old 老年代收集器

  1. Parallel Scavenger的老年代版本,1.6开始提供。
  2. 之前 Parallel Scavenger 只能配合Serial Old使用, 但在Server端下Serial Old 性能不是太好,这2个组合是反而吞吐率下来了。
  3. Paralle Old 出来后配合Parallel Scavenger 真正实现了 吞吐率优先 的收集器。

6.CMS 老年代收集器

  1. Concurrent Mark Sweep (CMS)以获取最短停顿时间为目标的收集器,1.5引入,基于标记-清除算法。
  2. 它的运作过程分为四个步骤:
    1. 初始标记  : 会Stop The World ,但仅仅标记GC Roots 可以直接关联到的下一级对象,而不是整个引用链,所以速度非常快。
    2. 并发标记  : 和用户线程一起执行,标记引用链中存活对象。
    3. 重新标记  : 修正并发标记后由于程序运行出现变动的对象。虽然Stop The World时间比初始标记要长但是相比并发标记就非常的短。
    4. 并发清除  : 和用户线程一起执行,清理内存。
  3. 缺点:
    1. 抢占了部分CPU资源
    2. 无法处理 浮动垃圾 ,在清理阶段产生的浮动垃圾无法处理,只能等到下次处理。
    3. 因为CMS 和用户线程并发执行所以不会和其他老年代收集器一样等到老年代满了才执行GC ,他在运行期会留出一部分空间以供其他线程使用,当预留空间不足时会出现Concurrent Mode Failare ,这样会使用Serial Old 收集,这样停顿时间就长了。
    4. 他是基于 标记-清除 的因此如果清除后碎片过多,这时候老年代虽然有大量空余空间但是找不到一个连续空间存放一个大对象,所以会触发Full GC 。
  4. 关于CMS的调优参数
    1. JVM CMS 常用参数配置

7.G1 收集器

  1. jdk1.7 加入 ,保留了分代概念,但内存分布不再是老年代和新生代2块。
  2. 特点:
    1. 并发与并行:缩短Stop The World 停顿时间
    2. 分代收集   : 无需配合可以独自管理GC堆,而且他能够采用不同的方式去处理新创建的对象、存活了一段时间的对象、熬过多次GC的对象以获取更好的收集效果。
    3. 空间整合   : G1整体看是属于 标记-整理,局部是属于 复制 算法实现,总之他不会产生碎片。
    4. 可预测停顿: 这是由于它管理的内存布局和其他收集器不同,所以让使用者设定在M毫秒的时间片段内在垃圾收集上的时间不超过N毫秒。这是相对于CMS的优势
  3. G1管理的GC堆的内存布局
    1. G1之前的收集器都是把新生代和老年代从物理上隔开并且收集范围是整个新生代或者老年代。
    2. G1把整个Java堆分成大小相等的独立区域 Region ,并且物理上不在连续。
  4. 收集方式不同
    1. G1之所以可以预测停顿是因为它不是在堆中进行全区域的垃圾收集,而是追踪每个Region中的垃圾回收价值(回收获得的空间大小和回收所需时间)的大小,后台维护一个优先队列,每次回收价值最大的。
    2. 收集动作:
      1. 初始标记 :仅仅只标记GC Roots根直接关联的对象
      2. 并发标记 :和用户线程一起执行,标记引用链中存活对象。
      3. 最终标记 :修正并发标记后由于程序运行出现变动的对象,把他们记录在 线程Remembered Set Logs 中,筛选回收阶段合并到Remembered Set 中。虽然Stop The World但可并行执行
      4. 筛选回收 :对Region的回收价值进行排序,按用户制定的停顿计划来回收。

8.Remembered Set

    1. 无论G1还是其他收集器,虚拟机就是使用Remembered Set 来避免全堆扫描存活对象。
    2. 当一个对一个引用的对象进行写操作时会产生一个 Writer Barrier 暂时中断写操作,检查该引用和其指向的对象是否在同一个Region中,分代中就是 老年代中的引用指向的对象是不是在老年代中,如果不是即不在同一个Region或者在新生代中则 将 相关引用信息记录到 对象所在的Region或者新生代的Remembered Set中(老年代没有Remembered Set)。
    3. 在枚举GC Roots 时 加入新生代或者每个Region的Remembered Set中的信息就可保证不对全堆扫描也不会把存活对象丢失。 
    4. OopMap 是用来枚举GC Root ,Remembered Set可以用来做可达性分析。
原文地址:https://www.cnblogs.com/mibloom/p/9605693.html