NOTE

7.10 3.垃圾回收器

1. JVM实际采用的垃圾回收算法:分代收集 根据对象的存活时间把内存分成新生代和老年代 - 新生代的特点是每次回收只有少量对象存活,因此采用改进的复制算法 改进的复制算法把内存空间分为Eden和Survivor区(8:1:1),只有10%的空间被浪费 - 老年代的特点是有大量对象存活,采用标记清除

Java创建于 更新于 historical

这是历史学习笔记,可能存在过时或不完整的理解。

1. JVM实际采用的垃圾回收算法:分代收集

根据对象的存活时间把内存分成新生代和老年代

  • 新生代的特点是每次回收只有少量对象存活,因此采用改进的复制算法 改进的复制算法把内存空间分为Eden和Survivor区(8:1:1),只有10%的空间被浪费
  • 老年代的特点是有大量对象存活,采用标记清除、标记整理算法

2. 垃圾收集器分类

2.1. 四大类七种垃圾回收器

  • Serial:单线程执行垃圾回收,同时暂停所有的用户线程
    • 新生代:Serial收集器
    • 老年代:Serial Old收集器
  • Parallel:多线程执行垃圾回收,同时暂停所有的用户线程
    • 新生代:ParNew收集器、Parallel Scavenge收集器
    • 老年代:Parallel Old收集器
  • CMS:多线程执行垃圾回收,不需要暂停用户线程
  • G1:

2.1.1. 如何开启

4.jvm参数选用具体的垃圾回收器.md

2.2. CMS详解

  1. 初始标记(initial mark):单线程执行且STW,但仅仅把GC Roots的直接关联可达的对象给标记一下,由于直接关联对象比较小,所以这里的速度非常快。
  2. 并发标记(concurrent mark):多线程执行但不用STW,对于初始标记过程所标记的初始标记对象,进行并发追踪标记,此时其他线程仍可以继续工作。此处时间较长,但不停顿。
  3. 重新标记(remark):单线程执行且STW,在并发标记的过程中,由于可能还会产生新的垃圾,所以此时需要重新标记新产生的垃圾。此处执行并行标记,与用户线程不并发,所以依然是“Stop The World”,时间比初始时间要长一点。
  4. 并发清除(concurrent sweep):多线程执行但不用STW,并发清除之前所标记的垃圾。其他用户线程仍可以工作,不需要停顿。

2.2.1. 日志分析

UTOOLS1584166071027.png

2.3. G1详解

  • 内存划分:宏观上看不在是年轻代、老年代的划分,分成N块region,每一块都有分代属性

  • 整体上使用标记整理,从而避免了内存碎片,局部使用复制算法

  • G1可以指定期望的停顿时间

  • 对于每一块的回收过程如下:

    1. 初始标记(initial mark):单线程执行且STW,标记了从GC Root开始直接关联可达的对象。
    2. 并发标记(concurrent marking):多线程执行但不用STW,并发标记初始标记的对象,此时用户线程依然可以执行。
    3. 最终标记(Remark):单线程执行且STW,,并发标记过程中可能产生新的垃圾,在标记一次
    4. 筛选回收(Live Data Counting And Evacuation):多线程执行但不用STW,评估标记垃圾,根据时间来筛选回收哪些垃圾

2.4. CMS vs G1

CMS G1
使用范围 老年代的收集器,可以配合新生代的Serial和ParNew收集器一起使用 收集范围是老年代和新生代。不需要结合其他收集器使用
目标 以最小的停顿时间为目标 可预测垃圾回收的停顿时间
内存碎片 使用“标记-清除”算法进行的垃圾回收,容易产生内存碎片 “标记-整理”算法,进行了空间整合,降低了内存空间碎片。
垃圾回收的过程不一样 2.2. CMS详解 2.3. G1详解

3. 参考链接