1. 概述

本文将快速介绍不同 JVM 垃圾收集(GC) 实现的基础知识,并演示如何在应用程序中启用特定类型的垃圾收集器。

2. 垃圾收集简介

从名称看,垃圾收集似乎只是查找并删除内存中的垃圾。但实际上,垃圾收集器会追踪 JVM 堆空间中的每个对象,并清除不再使用的对象。

GC 工作流程主要分为两个简单步骤,称为标记和清除:

  • 标记阶段:垃圾收集器识别哪些内存正在使用,哪些未被使用
  • 清除阶段:移除标记阶段识别出的无用对象

✅ 优势:

  • 无需手动处理内存分配/释放,GC 自动管理未使用内存
  • 避免处理悬垂指针的额外开销
  • 自动处理内存泄漏(GC 虽不能完全杜绝内存泄漏,但能解决大部分问题)

❌ 劣势:

  • JVM 需追踪对象引用的创建/删除,会消耗额外 CPU 资源,可能影响大内存请求的性能
  • 程序员无法控制释放无用对象的 CPU 时间调度
  • 某些 GC 实现可能导致应用不可预测地暂停
  • 自动化内存管理效率不如合理的手动内存分配/释放

3. GC 实现类型

JVM 提供四种 GC 实现:

  • Serial 垃圾收集器
  • Parallel 垃圾收集器
  • G1 垃圾收集器
  • Z 垃圾收集器

3.1. Serial 垃圾收集器

这是最简单的 GC 实现,采用单线程工作。运行时会冻结所有应用线程,因此不适合多线程应用(如服务器环境)

Twitter 工程师在 QCon 2012 的演讲中深入分析了 Serial GC 性能,值得参考。

Serial GC 适用于对暂停时间无要求且运行在客户端模式的应用。启用方式:

java -XX:+UseSerialGC -jar Application.java

3.2. Parallel 垃圾收集器

从 Java 5 到 Java 8 的默认 GC,又称吞吐量收集器。与 Serial GC 不同,它使用多线程管理堆空间,但执行 GC 时仍会冻结应用线程。

使用此 GC 可指定:

  • 最大 GC 线程数(-XX:ParallelGCThreads=<N>
  • 最大暂停时间目标(-XX:MaxGCPauseMillis=<N>
  • 最大吞吐量目标(-XX:GCTimeRatio=<N>
  • 最大堆内存(-Xmx<N>

启用方式:

java -XX:+UseParallelGC -jar Application.java

3.3. G1 垃圾收集器

G1(Garbage First) 专为多处理器大内存环境设计,自 JDK 7 Update 4 引入。

核心特性:

  • 将堆划分为等大小的区域
  • 通过并发全局标记阶段(标记阶段)确定对象存活状态
  • 优先回收空白区域(清除阶段),因此得名 "Garbage-First"

启用方式:

java -XX:+UseG1GC -jar Application.java

3.4. Java 8 新特性

Java 8u20 引入 字符串去重 功能(-XX:+UseStringDeduplication),通过将重复字符串值合并到全局 char[] 数组优化堆内存使用。

3.5. Z 垃圾收集器

ZGC(Z Garbage Collector) 是可伸缩的低延迟收集器:

  • Java 11 在 Linux 上作为实验性功能引入
  • JDK 14 支持 Windows 和 macOS
  • Java 15 起转为生产就绪

核心优势:

  • 所有昂贵操作并发执行,暂停时间不超过 10ms
  • 使用带色指针的加载屏障实现并发操作
  • 支持堆内存范围从 8MB 到 16TB
  • 暂停时间不随堆大小、存活对象或根集大小增加

⚠️ 注意:

  • 与 G1 类似分区堆,但区域大小可变
  • 非默认 GC

启用方式:

# JDK 15 之前(需开启实验模式)
java -XX:+UnlockExperimentalVMOptions -XX:+UseZGC Application.java

# JDK 15 及之后
java -XX:+UseZGC Application.java

4. 总结

本文分析了主流 JVM 垃圾收集器的实现原理及适用场景。更详细的调优文档可参考 Oracle 官方指南


原始标题:JVM Garbage Collectors

« 上一篇: Groovy语言入门
» 下一篇: MyBatis 快速指南