Java垃圾收集机制:核心算法、收集器与调优实践
一、垃圾收集算法:内存的清洁工
垃圾收集算法是 JVM 回收内存的核心。
1. 标记-清除(Mark-Sweep)
- 原理:首先标记所有存活的对象,然后清除所有未标记的对象。
- 优点:实现简单。
- 缺点:会产生大量的内存碎片。
2. 复制算法(Copying)
- 原理:将内存划分为两个大小相等的区域(
From区和To区)。每次回收时,将存活对象从From区复制到To区,然后清空From区。 - 优点:不会产生内存碎片,回收效率高。
- 缺点:内存利用率低,只适用于对象存活率低的新生代。
3. 标记-整理(Mark-Compact)
- 原理:在标记存活对象后,将所有存活对象移动到内存的一端,然后直接清理掉边界外的内存。
- 优点:内存连续,不会产生内存碎片。
- 缺点:移动对象会增加 GC 停顿时间。
二、垃圾收集器:算法的具体实现
垃圾收集器是垃圾收集算法的具体实现。在 JVM 中,有多种垃圾收集器,它们在停顿时间和吞吐量之间做出了不同的权衡。
1. CMS(Concurrent Mark Sweep)
- 目标:低延迟。
- 工作流程:
CMS采用“初始标记 -> 并发标记 -> 重新标记 -> 并发清除”的四阶段流程。其中,并发阶段允许 GC 线程和用户线程同时运行,从而减少了 GC 停顿时间。 - 缺点:会产生内存碎片,且对 CPU 敏感。
2. G1(Garbage-First)
- 目标:可预测的停顿时间。
- 核心思想:将堆内存划分为多个大小相等的 Region。
G1会优先回收垃圾最多的Region(Garbage-First),从而实现可预测的 GC 停顿。 - 优势:
G1能够控制停顿时间(通过-XX:MaxGCPauseMillis),且没有内存碎片问题。
3. ZGC/Shenandoah
-
目标:亚毫秒级停顿,适用于超大堆内存。
-
核心思想:
ZGC:使用染色指针技术,在指针中存储对象状态,实现了几乎完全并发的垃圾收集。Shenandoah:使用转发指针技术,实现了并发整理,无需 STW 即可移动对象。
三、GC调优与日志分析
GC 调优是一个系统工程,需要结合 GC 参数和日志分析。
-
GC 参数:
-Xmx:设置最大堆内存。-XX:+UseG1GC:启用G1收集器。-XX:MaxGCPauseMillis:设置最大 GC 停顿时间。
-
GC 日志:GC 日志记录了 GC 发生的时间、类型、停顿时间等信息。通过分析 GC 日志,可以定位 GC 瓶颈,并调整参数。
结论:
理解垃圾收集算法和收集器的工作原理,是 JVM 性能优化的关键。开发者需要根据应用的特点(如吞吐量、延迟、内存大小),选择合适的垃圾收集器和参数,从而实现最佳的性能平衡。