JVM(Java虚拟机)的垃圾回收器(Garbage Collector, GC)是管理内存自动回收的核心组件,负责回收不再使用的对象,释放内存空间。JVM提供了多种垃圾回收器,每种回收器都有其特定的适用场景和性能特点。

垃圾回收器的分类

按工作区域划分

  • 新生代回收器:负责回收新生代(Young Generation)的内存;

  • 老年代回收器:负责回收老年代(Old Generation)的内存;

  • 整堆回收器:同时负责新生代和老年代的内存回收。

按工作方式划分

  • 串行回收器(Serial GC):单线程执行垃圾回收,适合单核CPU或小型应用;

  • 并行回收器(Parallel GC):多线程执行垃圾回收,适合多核CPU和高吞吐量场景;

  • 并发回收器(Concurrent GC):在应用程序运行的同时执行部分垃圾回收工作,适合低延迟场景。

常见的垃圾回收器

Serial GC

  • 特点

    • 单线程执行垃圾回收。

    • 在垃圾回收时会暂停所有应用线程(Stop-The-World)。

  • 适用场景:单核CPU或客户端应用。

  • 启用参数-XX:+UseSerialGC

Parallel GC(吞吐量优先)

  • 特点

    • 多线程执行垃圾回收。

    • 关注高吞吐量,适合后台计算任务。

  • 适用场景:多核CPU、高吞吐量应用。

  • 启用参数-XX:+UseParallelGC

CMS GC(Concurrent Mark-Sweep)

  • 特点

    • 并发执行大部分垃圾回收工作,减少停顿时间。

    • 采用"标记-清除"算法,可能产生内存碎片。

  • 适用场景:低延迟应用,如Web服务器。

  • 启用参数-XX:+UseConcMarkSweepGC(在JDK 9及以上版本已弃用)

G1 GC(Garbage-First)

  • 特点

    • 将堆内存划分为多个区域(Region),优先回收垃圾最多的区域。

    • 兼顾吞吐量和低延迟。

  • 适用场景:大内存、多核CPU的应用。

  • 启用参数-XX:+UseG1GC

ZGC(Z Garbage Collector)

  • 特点

    • 支持超大堆内存(TB级别)。

    • 停顿时间极短(通常不超过10ms)。

  • 适用场景:超大内存、低延迟应用。

  • 启用参数-XX:+UseZGC(需要JDK 11及以上版本)

Shenandoah GC

  • 特点

    • 与ZGC类似,专注于低停顿时间。

    • 与ZGC相比,Shenandoah GC在JDK 12中成为正式特性。

  • 适用场景:低延迟、大内存应用。

  • 启用参数-XX:+UseShenandoahGC(需要JDK 12及以上版本)

垃圾回收器的工作原理

垃圾回收器的工作通常分为以下几个阶段:

标记(Mark)

  • 遍历堆内存,标记所有存活的对象;

  • 从GC Roots(如栈帧、静态变量等)开始,递归标记所有可达对象。

清除(Sweep)

  • 回收未被标记的对象,释放内存空间;

  • 在“标记-清除”算法中,可能会产生内存碎片。

压缩(Compact)

  • 将存活对象移动到内存的一端,消除内存碎片,在“标记-整理”算法中使用。

复制(Copy)

  • 将存活对象从一个内存区域复制到另一个区域,在新生代的垃圾回收中常用。

垃圾回收器的调优

通过调整JVM参数,可以优化垃圾回收器的性能。以下是一些常见的调优参数:

堆大小

  • -Xms:初始堆大小;

  • -Xmx:最大堆大小。

新生代大小

  • -XX:NewSize:初始新生代大小;

  • -XX:MaxNewSize:最大新生代大小。

GC日志

  • -XX:+PrintGCDetails:打印GC详细信息;

  • -Xloggc:<file>:将GC日志输出到文件。

示例

以下是一个启用G1 GC的JVM参数示例:

java -XX:+UseG1GC -Xms512m -Xmx2g -XX:MaxGCPauseMillis=200 -jar app.jar
  • -XX:+UseG1GC:启用G1 GC;

  • -Xms512m:初始堆大小为512MB;

  • -Xmx2g:最大堆大小为2GB;

  • -XX:MaxGCPauseMillis=200:设置最大停顿时间为200ms。