JVM 垃圾收集器相关知识总结
一、基本概念
垃圾收集(Garbage Collection,GC)是Java等编程语言中用于自动管理内存的一种机制。它通过回收不再使用的对象所占用的内存,以避免内存泄漏和确保程序的稳定运行。
二、收集方式分类
按工作模式不同:指的是GC线程和工作线程是否一起运行
-
独占垃圾回收器:只要GC在工作,STW 一直进行到回收完毕,工作线程才能继续执行;
-
并发垃圾回收器:让GC线程垃圾回收的某些阶段 可以和 工作线程一起进行。
按回收线程数:指的是GC线程是否串行或并行执行
-
串行垃圾回收器:一个GC线程完成内存资源的回收工作;
-
并行垃圾回收器:多个GC线程同时一起完成内存资源的回收工作,充分利用CPU的多核并发执行的计算资源。
三、常见垃圾回收器方案
-
新生代可以适用的垃圾回收器:Serial(串行收集器)、ParNew(并行年轻代收集器)、Parallel Scavenge(并行回收器)。
Serial:单线程的年轻代垃圾回收器,适用于单核处理器或对暂停时间要求不高的场景。
ParNew:Serial 的多线程版本,可利用多核处理器优势,在多处理器环境下能更快完成垃圾回收。
Parallel Scavenge:关注吞吐量的年轻代垃圾回收器,适合在后台运行且不需要快速响应的任务,目标是在单位时间内完成更多工作。 -
老年代可以适用的垃圾回收器:CMS(并发标记-清除收集器)、Serial Old(串行老年代收集器)、Parallel Old(并行老年代收集器)。
CMS(Concurrent Mark Sweep):以获取最短回收停顿时间为目标的老年代垃圾回收器,在垃圾回收过程中能与应用程序线程并发执行,适合对响应时间敏感的应用。
Serial Old:单线程的老年代垃圾回收器,通常作为 CMS 发生 Concurrent Mode Failure 时的后备方案。
Parallel Old:Parallel Scavenge 对应的老年代版本,关注吞吐量,与 Parallel Scavenge 搭配使用,在多核处理器上能有效利用资源进行垃圾回收。 -
新生代和老年代混合回收器:G1(Garbage First 收集器)和 ZGC(Z Garbage Collector)回收器。
G1(Garbage - First):整体上采用标记 - 整理算法,局部采用复制算法,不再区分传统的年轻代和老年代,而是将堆划分为多个 Region。它能预测停顿时间,优先回收价值最大的 Region,适用于大内存且对停顿时间有严格要求的应用。
ZGC(Z Garbage Collector):低延迟垃圾回收器,支持 TB 级别的堆内存,停顿时间可控制在 10ms 以内,通过着色指针和读屏障等技术实现并发回收。
四、串行收集器Serial
单线程、独占式串行,采用复制算法0,简单高效但会造成STW。这是最基础的单线程垃圾回收器,在进行垃圾回收时,整个应用程序会完全停顿,直到回收完成。
-
新生代:采用复制算法(将存活对象复制到空闲区域,清理原区域);
-
老年代:采用标记 - 整理算法(标记存活对象,将其紧凑排列以消除碎片)。
优缺点
-
优点:实现简单,内存占用极低(无需多线程协调开销),单线程下效率高(无线程切换成本);
-
缺点:STW 时间长(随堆大小增加而增长),无法利用多 CPU 资源,不适合高并发场景。
适用场景
-
客户端应用(如桌面程序、工具类软件),堆内存较小(通常小于 1GB);
-
单 CPU 环境或资源受限的嵌入式设备。
五、并行回收收集器Parallel
随着硬件资源的升级,包括内存空间的增大和 CPU 的多核化,传统的 Serial 垃圾收集器面临着性能瓶颈。由于它采用单线程执行垃圾回收操作,无法充分利用多核 CPU 的优势,导致在处理大内存空间时性能下降,垃圾回收时间变得更长。
为了充分发挥多核 CPU 的优势,JVM 推出了 Parallel 收集器系列。Parallel 收集器的设计思想是利用多线程并行执行垃圾回收操作,以提高整个垃圾收集过程的并行度和性能。
相比于传统的 Serial 收集器,Parallel 收集器能更好地适应现代应用的需求,特别是大型内存堆和高吞吐量的场景。
多线程并行、独占式,会产生STW,使用复制算法关注调整吞吐量。此收集器核心目标是提高吞吐量:吞吐量 = 运行用户代码时间/(运行用户代码时间+垃圾收集时间)
-
新生代:多线程执行复制算法,并行收集;
-
老年代:多线程执行标记 - 整理算法,并行收集;
注:仍会触发 STW,但因多线程并行,STW 时间比 Serial GC 短。
优缺点
-
优点:吞吐量高(适合后台计算),多 CPU 下效率优于 Serial GC,可通过参数(如-XX:MaxGCPauseMillis)控制最大 STW 时间;
-
缺点:STW 时间仍可能较长(尤其堆较大时),对响应时间敏感的应用不友好。
适用场景
-
批处理任务(如数据分析、日志处理);
-
适合在后台运算而不需要太多交互的任务,优先追求高吞吐量而非低延迟。
六、无代限制收集器G1
随着硬件资源的不断升级,可用的内存资源越来越多,这对于垃圾收集器的发展提出了新的挑战。
传统的垃圾收集器采用物理分区的方式将内存分为老年代、新生代、永久代或 MetaSpace,但随着可用内存的增加,某一分代区域的大小可能会达到几十上百 GB。在这种情况下,传统的物理分区收集方式会导致垃圾扫描和清理时间变得更长,性能下降。
G1 垃圾收集器摒弃了传统的物理分区方式,而是将整个内存分成若干个大小不同的 Region 区域。每个Region 在逻辑上组合成各个分代,这样做的好处是可以以 Region 为单位进行更细粒度的垃圾回收。G1 垃圾收集器在进行垃圾回收时,可以针对单个或多个 Region 进行回收,从而提高了收集效率和性能。
核心思想
“优先回收垃圾最多的 Region”(Garbage-First),通过混合收集(同时回收部分新生代和老年代 Region)平衡吞吐量和延迟。
优缺点
-
优点:兼顾吞吐量和响应时间,STW 可控(适合对延迟有要求的场景),支持大堆且内存碎片少;
-
缺点:内存占用和 CPU 消耗较高(需维护 Region 元数据),小堆下性能可能不如 Parallel GC。
适用场景
-
大型企业级应用(如电商平台、支付系统);
-
堆内存较大,需要平衡吞吐量和响应时间的服务。
七、如何根据应用类型选择垃圾收集器?
选择的核心依据是应用的核心需求(延迟 / 吞吐量)、资源限制(堆大小、CPU 核心数)等,一般情况下可使用以下原则:
-
客户端或较小程序,内存使用量不大,单 CPU 或资源受限,可以使用串行回收Serial
-
对于服务端大型计算,有限吞吐量,可以使用并行回收Parallel
-
大型WEB应用,用户端不愿意等待,尽量少的STW,优先响应时间(低延迟),可以使用无代限制收集器G1