JVM之垃圾回收

目录

一、引言

二、垃圾回收对象标准

三、垃圾回收算法

1.标记-清除算法(Mark-Sweep)

2.标记-整理算法(Mark-Compact)

3.标记-拷贝算法(Mark-Copy)

四、垃圾回收器

1.Serial回收器

2.CMS回收器

3.G1回收器


一、引言

Java 会对内存进行自动分配与回收管理,使上层业务更加安全,方便地使用内存实现程序逻辑。在不同的 JVM 实现及不同的回收机制中,堆内存的划分方式是不一样的。这里简要介绍垃圾回收( Garbage Collection, GC )。垃圾回收主要目的清除不再使用的对象自动释放内存

二、垃圾回收对象标准

GC 是如何判断对象是否可以被回收的呢?为了判断对象是否存活, JVM 引入了 GC Roots如果一个对象与 GC Roots 之间没有直接间接的引用关系,比如某个失去任何引用的对象,或者两个互相环岛状循环引用的对象等,判决这些对象“死缓 ”,是可以被回收的。什么对象可以作为 GC Roots 呢?比如类静态属性中引用的对象常量引用的对象虚拟机栈中引用的对象本地方法栈中可引用的对象等。

三、垃圾回收算法

有了判断对象是否存活的标准后,再了解一下垃圾回收的相关算法。最基础的为"标记-清除算法"

1.标记-清除算法(Mark-Sweep

该算法会从每个GC Roots 触发,依次标记有引用关系的对象,最后将没有被标记的对象清除。但是这种算法会带来大量的空间碎片,导致需要分配一个较大连续空间时容易触发 FGC(全堆范围的GC)。为了解决这个问题,又提出了"标记一整理算
法"。

JVM之垃圾回收

JVM之垃圾回收

2.标记-整理算法(Mark-Compact)

该算法类似计算机的碰盘整理,首先会从 GC Roots 出发标记存活的对象,然后将存活对象整理到内存空间的一端形成连续的已使用空间,最后把已使用空间之外的部分全部清理掉,这样就不会产生空间碎片的问题。

JVM之垃圾回收

JVM之垃圾回收

3.标记-拷贝算法(Mark-Copy

为了能够并行地标记和整理将空间分为两块,每次只**其中一块,垃圾回收时只需把存活的对象复制到另一块未**空间上,将未**空间标记为己**,将己**空间标记为未**,然后清除原空间中的原对象。堆内存空间分为较大的 Eden 和两块较小的 Survivor,每次只使用 Eden 和 Survivor 区的块。这种情形下的" Mark-Copy "减少了内存空间的浪费。

JVM之垃圾回收

JVM之垃圾回收

 

" Mark-Copy " 现作主流的YGC算法进行新生代的垃圾回收

四、垃圾回收器

垃圾回收器(Garbage Collector)是实现垃圾回收算法应用在 JVM 环境中内存管理模块。当前实现的垃圾回收器有数十种,下面只介绍 Serial 、CMS 、G1 三种。

1.Serial回收器

Serial 回收器是一个主要应用于 YGC 的垃圾回收器,采用行单线程的方式完成 GC 任务,其中“ Stop The World ”简称 STW,即垃圾回收的某个阶段会暂停整个应用程序的执行。FGC 的时间相对较长,频繁 FGC 会严重影响应用程序的性能。主
要流程如下图所示。

JVM之垃圾回收

2.CMS回收器

CMS 回收器(Concurrent Mark Sweep Collector)是回收停顿时间比较短目前比较常用的垃圾回收器。它通过初始标记(Initial Mark)、并发标记(ConcurrentMark) 、重新标记(Remark) 、并发清除(Concurrent Sweep) 四个步骤完成垃圾回收工作。第 1 、3 步的初始标记和重新标记阶段依然会引发 STW(Stop The World),而第2、4 步的并发标记和并发清除两个阶段可以和应用程序并发执行,也是比较耗时的操作,但并不影响应用程序的正常执行。由于 CMS 采用的是 "标记-清除算法",因此产生大量的空间碎片。为了解决这个问题,CMS 可以通过配置-XX:+UseCMSCompactAtFullCollection 参数,强制 JVM 在 FGC 完成后对老年代进行压缩,执行一次空间碎片整理,但是空间碎片整理阶段也会引发 STW。为了减少 STW 次数, CMS 还可以通过配置-XX :+CMSFullGCsBeforeCompaction=n 参数,在执行了 n 次 FGC 后,JVM 再在老年代执行空间碎片整理。

3.G1回收器

Hotspot 在 JDK7 中推出了新一代 G1 ( Garbage-First Garbage Collector) 垃圾回收 ,通过-XX:+UseG1GC 参数启用。和 CMS 相比,G1 具备压缩功能,能避免碎片问题,G1 的暂停时间更加可控。性能总体还是非常不错的,简要结构如下图

JVM之垃圾回收

G1 将 Java 堆空间分割成了若干相同大小的区域,即 region,包括 Eden 、Survivor 、Old 、Humongous 四种类型。其中,Humongous 是特殊的 Old 类型,专门放置大型对象。这样的划分方式意味着不需要一个连续的内存空间管理对象。 G1 将
空间分为多个区域,优先回收垃圾最多的区域。G1 采用的是"Mark-Copy",有非常好的空间整合能力,不会产生大量的空间碎片。G1 的一大优势在于可预测的停顿时间,能够尽可能快地在指定时间内完成垃圾回收任务。在 JDK11 中,已经将 G1 设为默认垃圾回收器,通过 jstat 命令可以查看垃圾回收情况,如下图所示,在 YGC 时 S0/S1 并不会交换。

JVM之垃圾回收