Java垃圾收集

fyh 2022年09月11日 52次浏览

Java垃圾收集

基本流程:new->新生代->存活区->老年代->OOM

收集算法

  • 计数引用法:引用+1,停止引用-1,到0回收。
  • 标记清除法:从根出发找到所有引用并清理。(造成垃圾碎片)
  • 标记压缩法:标记清除基础上进行整理。
  • 复制算法:将内存分为两部分,每次只用一部分。(适用新生代,不适合老年代)
  • 分代算法:新生代由于会存储大量新生对象,适合复制算法。老年代回收可能性不高,所以适合标记清除法或标记压缩法。

CMS

  • 初始标记:短暂STW,扫描根关联对象
  • 并发标记:开一个CMS标记线程与其它线程一起执行
  • 并发预清理:查找并发标记阶段进入老年代对象,重新扫描
  • 重新标记:短暂STW,对并发标记阶段改变引用或新创建的对象进行标记
  • 并发清理:开一个CMS清理线程与其它线程一起执行
  • 并发重置:重置CMS收集器为初始状态等待下一次收集

G1

取消堆内存中新生代和老年代物理结构划分,将一块完整的物理内存拆分为若干子区域,每一块子区域可能是伊甸园区、存活区、老年区、巨型区中的一种。避免全局GC操作,减少STW时间。

CSet(Collect Set):G1收集器会同时进行N个垃圾最多的区域回收,需要区维护一个区域链表,该链表保存回收后的区域

  • Young GC:该模式下CSet只包含新生代区域
  • Mixed GC:该模式会选择所有新生代区域并选择一部分老年代区域(选择存活对象最少的区域回收)。
  • Full GC:如果对象内存分配速度过快,Mixed GC来不及回收内存,就会触发Full GC。G1 收集器的Full GC

RSet(Remember Set):记录非收集区指向收集区的指针集合。G1垃圾收集器中每个区域都有RSet,记录了其他区域的对象引用关系,这样在回收一个区域时不需要全堆扫描,只要检查RSet就可以找到其外部引用。

SATB:增量式标记清除垃圾收集器设计的标记算法。主要针对并发标记阶段。SATB创建了对象图,privious位图保存最近一次完成的标记信息,并发标记中创建更新next位图,previous位图会越来越过时,最终并发标记结束时被next位图覆盖。

  • 新生代垃圾收集:伊甸园区耗尽触发新生代GC,触发极短STW,随后基于多线程方式收集,若某些对象回收后依然存活,则进入老年代
  • 并发标记:使用SATB算法
    • 初始标记:通常和新生代GC一起进行,短暂STW
    • 根分区扫描:扫描存活区,存活区引用对象会被标记,不会STW
    • 并发标记:多线程实现,将标记结果保存在全局列表中
    • 重新标记:产生STW,处理剩下SATB日志缓冲区和所有更新的引用,找出未被标记的存活对象
    • 清理阶段:主要通过老年代回收
  • 混合GC:会多次执行,一直到几乎所有标记老年代分区被回收,然后又回到新生代垃圾收集周期。