Page cover image

JVMG1

JVM Garbage First

Java有三个基础GC 算法

Mark-Sweep标记清除

它分为两个阶段:标记和清除。

标记阶段会遍历所有可达的对象,并将它们标记为存活。清除阶段会删除所有未被标记的对象,即垃圾对象。

这种算法的优点是实现简单,不需要额外的空间。缺点是会产生内存碎片,导致后续分配大对象时可能失败。

Copying拷贝

一种将内存分为两个相等的区域,每次只使用其中一个区域的算法。当这个区域快要用完时,就会将存活的对象复制到另一个区域,并清空原来的区域。

这种算法的优点是不会产生内存碎片,且复制过程中不需要暂停应用程序。缺点是浪费了一半的内存空间,且复制大量对象时会影响性能

Mark-Compact标记压缩

一种结合了标记清除和拷贝算法的思想的算法。它也分为两个阶段:标记和压缩。

标记阶段和标记清除算法相同,都是遍历所有可达的对象,并将它们标记为存活。压缩阶段则是将所有存活的对象向内存空间的一端移动,并更新它们的引用地址。

这种算法的优点是既不会浪费内存空间,又不会产生内存碎片。缺点是移动对象和更新引用地址时需要暂停应用程序。

Java有两种GC模型

  • 分代模型

  • 分区模型

在这两种模型之上,Java建立了10中GC,如下图

分代Young
分代Old
分区模型

ParNew

Copying

CMS

Mark-Sweep

G1

Copying和Mark-Compact

Serial

Copying或Mark-Compact

SO

Mark-Compact

ZGC

Copying和Mark-Compact

PS

Copying

PO

Mark-Compact

Shenandoah

Copying和Mark-Compact

分代模型年轻代GC

A stop-of-world(STW), copying collector which uses a single GC thread.

垃圾到一定程度后,所有业务线程停止,GC开始工作。会导致Java程序运行到一定时候出现卡顿。

GC的标记阶段一般采用三色标记法,但是存在诸多bug,同时也会提到CMS对其解决方案。

其一如下

A及其子已经标记到,B被标记到但其子未标记,D还未标记,此时标记任务停止,业务任务启动

A新引用了D,B取消引用D,变成下图,此时业务任务停止,标记任务启动

标记任务从灰色B继续标记,发现没有子,于是一轮结束,标记AB为有效,D为垃圾。

解决方案有很多,其一如下

在JVM中设计一种屏障,一旦观察到黑色向白色建立引用,将此黑色修正为灰色。这就是CMS对三色标记的修正方案,称为Incremental Update,不过这种方案仍然有非常隐秘的问题,比如A有属性1,2,标记任务将1标记完后,2还没标记,中止切换到业务任务,将1引用

Last updated