垃圾收集算法

  • 标记-复制算法
    将内存分成两块且相同大小,每次只使用一块,当该块内存使用满时,将存活的对象复制到另一块内存中。比较浪费内存, 优点是不会产生内存碎片。
  • 标记-清除算法
    • 由于需要收集的内存较大,存在效率问题
    • 收集完垃圾后没有整理内存空间,会产生内存碎片
  • 标记-整理算法

垃圾收集器

CMS收集器


收集过程

CMS

  1. 初始标记: 标记GC Roots根直接引用的对象, 会STW
  2. 并发标记: 从初始标记后的结果向下标记, 期间产生新对象会直接标记为黑色.
  3. 重新标记: 标记由并发标记阶段产生的漏标对象, 使用增量更新方式.
  4. 并发清理: 清理所有白色对象, 即垃圾对象. 期间产生新对象会直接标记为黑色.
  5. 并发重置: 清理对象的三色标记.
多标和漏标

并发标记阶段会产生多标和漏标的对象.

  • 多标-浮动垃圾
    • 由于存在用户线程, 会导致部分已经标记的局部变量被销毁变成浮动垃圾
    • 由于存在用户线程, 产生的新对象也可能会变成浮动垃圾
  • 漏标-读写屏障
    • 三色标记

      黑色: 所有直接引用都标记了的对象.
      灰色: 至少存在一个引用未被标记的对象.
      白色: 没有被扫描到的对象.

    • 增量更新算法

      当对象引用发生改变时, 通过后置写屏障将该对象记录到队列中, 并将该对象设为灰色, 后续再从队列中取出对象进行重新标记。
      相较与SATB会减少浮动垃圾, CMS垃圾收集器就是使用了该算法.

    • SATB算法

      当对象引用删除时, 通过前置写屏障将原引用对象记录到队列中, 后续再进行重新标记。

注:由于并发标记和并发清理存在用户线程,所以可能出现未GC完就又触发了FullGC,即concurrent mode failure, 此时会进入STW并使用serial old来收集垃圾,且过程不可逆。

CMS核心参数
参数 作用
-XX:+UseConcMarkSweepGC 开启CMS
-XX:ConcGCThreads 设置GC并发线程数
-XX:+UseCMSCompactAtFullCollection FullGC后做碎片整理
-XX:CMSFullGCsBeforeCompaction 设置多少次FullGC之后整理一次碎片
-XX:CMSInitiatingOccupancyFraction 设置老年代达到多少比例时触发FullGC
-XX:+CMSScavengeBeforeRemark 设置在FullGC前启动一次minor gc
-XX:+CMSParallellnitialMarkEnabled 开启初始标记时多线程执行
-XX:+CMSParallelRemarkEnabled 开启重新标记时多线程执行

G1收集器


G1适用于多核且大内存的服务器

内部结构

G1
上图中的每个小格子称为一个region, 每个region大小相等,且不超过2048个region(JVM默认将堆内存划分成2048个region)。
新生代初始(默认)占比为5%,会随着系统运行动态的进行分配,但是最多不超过60%。年轻代的内部结构还是和之前的垃圾收集器一样,存在E区和S区,且E:S0:S1=8:1:1
Humongous用于存储大对象,当对象大小大于E区的50%时,会直接放进H区。比如每个region大小为2M,新对象大小大于1M时就会放入H区。FullGC时会回收H区。

收集过程

G1GC

  1. 初始标记(STW):同CMS的初始标记
  2. 并发标记:同CMS的并发标记
  3. 最终标记(STW):同CMS的重新标记
  4. 筛选回收(STW):根据设定的GC停顿时间(默认200ms)来制定回收计划,优先选择回收价值较大的region,最终计算出来需要回收的region称为Collection set。由于存在最大停顿时间,所以并不是每次GC都可以将所有垃圾都清理掉,未清掉的垃圾会在下一次FullGC再次清理。

从整体看,G1使用了"标记-整理"算法, 在回收region的时候采用的又是复制算法。所以G1几乎不存在内存碎片问题。

垃圾回收种类
  • Young GC
    E区放不下新对象时,G1会优先计算出回收当前E区所需时间,若远小于设定的停顿时间,G1会将对象放入新的E区,而不会触发GC。
  • Mixed GC
    当老年代占比达到设定的阈值触发。根据停顿时间,回收年轻代和部分老年代以及H区。
  • Full GC
    在Mixed GC回收过程中,如果没有多余的region供复制使用,则会触发FullGC。会STW且单线程回收。
G1核心参数
参数 作用
-XX:+UseG1GC 开启G1收集器
-XX:ParallelGCThreads 设置GC工作的线程数量
-XX:G1HeapRegionSize 设置region大小(1MB~32MB,且必须是2的N次幂)
-XX:MaxGCPauseMillis 设置暂停时间
-XX:G1NewSizePercent 设置新生代初始空间,默认5%
-XX:G1MaxNewSizePercent 设置新生代最大空间比例,默认60%
-XX:MaxTenuringThreshold 最大年龄阈值(默认15)
-XX:InitiatingHeapOccupancyPercent 设置老年代触发GC的空间占比
-XX:G1MixedGCLiveThresholdPercent 设置region中存活对象比例阈值,若小于则会在GC时优先回收,默认85%
-XX:G1MixedGCCountTarget 设置筛选回收阶段分几次做,默认8次