当前位置:首页 > 文章列表 > 文章 > java教程 > 垃圾收集器有哪些?Serial、ParNew、CMS、G1、ZGC详解

垃圾收集器有哪些?Serial、ParNew、CMS、G1、ZGC详解

2025-09-25 12:47:59 0浏览 收藏

编程并不是一个机械性的工作,而是需要有思考,有创新的工作,语法是固定的,但解决问题的思路则是依靠人的思维,这就需要我们坚持学习和更新自己的知识。今天golang学习网就整理分享《垃圾收集器有哪些?Serial、ParNew、CMS、G1、ZGC全解析》,文章讲解的知识点主要包括,如果你对文章方面的知识点感兴趣,就不要错过golang学习网,在这可以对大家的知识积累有所帮助,助力开发能力的提升。

答案:Java垃圾收集器根据应用场景选择,Serial单线程适合小内存,ParNew配合CMS降低停顿,CMS追求低延迟但有碎片问题,G1兼顾吞吐与延迟,ZGC实现毫秒级停顿支持大堆,选择时需权衡延迟、吞吐、堆大小及JDK版本,并通过GC日志分析优化。

你知道哪些垃圾收集器?(Serial, ParNew, CMS, G1, ZGC)

Java的垃圾收集器,说白了,就是JVM里负责回收不再使用的内存空间的“清洁工”。我们常用的主要有Serial、ParNew、CMS、G1,以及更现代的ZGC。它们各有特点,有的追求极致吞吐量,有的侧重低停顿,选择哪个,往往取决于你的应用场景和对性能的具体要求。

解决方案

在我看来,理解这些垃圾收集器,就像是了解不同类型的引擎,每款都有其设计哲学和适用领域。

Serial收集器 Serial,顾名思义,就是单线程的。它在进行垃圾收集时,会暂停所有用户线程(也就是我们常说的“Stop-The-World”,简称STW),直到垃圾收集完成。新生代采用复制算法,老年代采用标记-整理算法。它的优点是简单、高效,因为没有线程切换的开销。在单核CPU或者堆内存很小的客户端应用中,Serial GC的表现其实不赖。但对于服务器端应用,尤其是在多核处理器普及的今天,它的STW时间往往是不可接受的,想象一下你的服务突然卡住几百毫秒甚至几秒,那体验可太糟糕了。我个人觉得,它更多是作为一种“教学模型”和某些特定小场景下的备选。

ParNew收集器 ParNew是Serial的多线程版本,它在新生代使用多线程进行垃圾收集,同样会触发STW。老年代通常与CMS配合使用。既然是多线程,在多核CPU环境下,它的STW时间会比Serial短很多。它出现的意义,很大程度上是为了配合CMS,因为CMS在新生代无法独立完成收集工作,需要一个多线程的收集器来搭档。所以,你很少会单独配置ParNew,它几乎总是和CMS一起出现。

CMS(Concurrent Mark Sweep)收集器 CMS,并发标记清除,是HotSpot虚拟机中第一款真正意义上的并发收集器。它的目标是获取最短的停顿时间,所以它在收集的大部分时间里,都可以和用户线程一起工作。它主要分为四个阶段:

  1. 初始标记(Initial Mark):STW,但时间很短,标记GC Roots能直接关联到的对象。
  2. 并发标记(Concurrent Mark):与用户线程并发执行,遍历所有可达对象。
  3. 重新标记(Remark):STW,修正并发标记期间因用户程序运行导致的对象引用变动。这个阶段通常比初始标记长,但比新生代GC短。
  4. 并发清除(Concurrent Sweep):与用户线程并发执行,清除已标记的垃圾。 CMS的优点显而易见:低停顿。但它也有几个让我头疼的地方:
  • 对CPU资源敏感:并发阶段会占用一部分CPU资源,影响应用吞吐量。
  • 无法处理“浮动垃圾”:在并发清除阶段产生的垃圾,只能留到下一次GC再处理。
  • 空间碎片问题:标记-清除算法的通病,会产生大量不连续的内存碎片,当碎片过多时,可能会提前触发Full GC,而Full GC时,CMS会退化成Serial GC,导致长时间STW。
  • 并发失败(Concurrent Mode Failure):如果在并发清除过程中,预留的内存不足以支撑用户程序运行,就会触发Full GC。

我曾经在一些老项目中遇到过CMS的碎片问题,那真是让人抓狂,服务隔一段时间就卡顿一下,排查起来很费劲。

G1(Garbage-First)收集器 G1是JDK 7u4版本开始提供,并在JDK 9之后成为默认的垃圾收集器。它在设计上就考虑到了大堆内存和可预测的停顿时间。G1将Java堆划分为多个大小相等的Region(区域),每个Region可以扮演新生代、老年代,甚至是巨型对象区域。它的工作原理是:

  1. 全局并发标记:与CMS类似,进行并发标记。
  2. 停顿预测模型:这是G1的核心,它会维护每个Region的垃圾回收价值(回收所需时间、能回收多少空间),然后根据用户设定的停顿时间目标(MaxGCPauseMillis),优先回收那些垃圾最多、回收效率最高的Region。 G1的优点在于:
  • 可预测的停顿时间:通过Region的划分和停顿预测模型,可以尽可能地满足用户设定的停顿时间目标。
  • 避免碎片:G1在回收Region时,采用的是复制算法或标记-整理算法,所以不会产生内存碎片。
  • 兼顾吞吐量和延迟:在平衡这两者上做得很好。 对我而言,G1是目前最“省心”的收集器之一,尤其是在处理几十GB甚至上百GB堆内存的应用时,它的表现非常稳健。

ZGC ZGC是JDK 11引入的,旨在实现极低的停顿时间(通常在10ms以内,甚至1ms左右),并且停顿时间不随堆内存大小而变化。它的设计目标是支持TB级别的堆内存。ZGC的核心技术包括:

  • 着色指针(Colored Pointers):将一些元数据信息直接存储在对象指针中,减少查找时间。
  • 读屏障(Read Barrier):在对象读取时插入屏障,保证并发收集的正确性。
  • Region管理:与G1类似,也是基于Region的。 ZGC几乎所有的工作都是并发进行的,包括标记、重定位等。这使得它的STW时间极短。 它的优点显而易见:超低停顿,支持超大堆。但缺点是:
  • 对硬件要求高:需要64位操作系统。
  • 吞吐量可能略低于G1:因为读屏障会有一些开销。
  • JDK版本要求高:目前仅在JDK 11及更高版本中可用。 我个人对ZGC充满期待,在对延迟要求极其苛刻的场景,比如金融交易系统、实时大数据处理,ZGC简直是“神兵利器”。但对于一般的Web应用,G1可能已经足够好。

如何根据应用特性选择合适的垃圾收集器?

选择垃圾收集器,从来都不是一道简单的选择题,它更像是一场对应用需求和JVM机制的深度博弈。我的经验是,没有“最好”的收集器,只有“最适合”你应用的。

  1. 关注你的核心指标

    • 吞吐量(Throughput)优先? 如果你的应用是批处理、数据分析等,可以接受较长的停顿,但希望在单位时间内处理更多任务,那么Parallel GC(不是本文讨论的重点,但它就是高吞吐量代表)或者G1在某些配置下会是好的选择。
    • 延迟(Latency)优先? 如果你的应用是Web服务、实时交易系统、GUI应用,对响应时间非常敏感,那么CMS、G1或者ZGC是你的首选。
    • 堆内存大小
      • 小堆(几百MB到1GB):Serial GC或Parallel GC可能表现不错,甚至G1在这种情况下也可能有点“杀鸡用牛刀”。
      • 中等堆(1GB到4GB):G1通常是个不错的通用选择。CMS也可以考虑,但要警惕碎片问题。
      • 大堆(4GB到几十GB甚至TB):G1是目前最稳妥的选择。如果对停顿要求极高,ZGC(JDK 11+)或Shenandoah(JDK 12+)则能提供更极致的体验。
  2. 考虑JDK版本

    • JDK 8及以前:G1是可选的,但默认可能不是。CMS是低延迟的代表。
    • JDK 9及以后:G1成为默认GC。ZGC和Shenandoah等新一代收集器也逐渐成熟。新版本通常意味着对GC的优化和新特性。
  3. CPU核数

    • 单核或双核:Serial GC或ParNew在小堆下可能还行。但多核是主流,多线程GC的优势明显。
    • 多核:ParNew、CMS、G1、ZGC都能很好地利用多核并行处理能力。
  4. 实际测试与观察: 这可能是最重要的一点。理论分析是基础,但实际应用的负载、数据模式、对象生命周期都会影响GC表现。我的建议是:

    • 从默认GC开始,或者根据上述原则选一个初步的GC。
    • 在生产环境或类生产环境进行压力测试。
    • 务必收集GC日志(-Xlog:gc*-XX:+PrintGCDetails -XX:+PrintGCDateStamps 等)。
    • 使用GCViewer、JConsole、VisualVM等工具分析GC日志,观察停顿时间、GC频率、内存使用情况。
    • 根据分析结果,逐步调整JVM参数,比如新生代和老年代的比例、最大停顿时间目标等。

举个例子,如果我有一个电商后台服务,对响应时间有一定要求,同时堆内存可能在8GB左右,我会毫不犹豫地选择G1。如果这是一个实时金融风控系统,对毫秒级的延迟都不能容忍,并且堆内存可能达到几十GB,那么ZGC会是我的重点考察对象。

垃圾收集器调优有哪些常见误区和最佳实践?

GC调优,很多人一上来就想改参数,但往往忽略了更本质的问题。我见过太多因为不当调优导致性能更差的案例。

常见误区:

  1. 盲目追求低延迟:为了追求极致的低停顿,不惜牺牲吞吐量。结果是GC虽然快了,但应用处理请求的能力下降,整体性能反而变差。要知道,GC的本质是内存管理,吞吐量和延迟往往是此消彼长的关系。
  2. 过度配置GC参数:JVM提供了大量的GC参数,但不是每个参数都需要你动。很多参数是相互关联的,改一个可能影响多个地方。不理解参数含义就随意修改,往往会适得其反。
  3. 不看GC日志就调优:没有数据支撑的调优都是“玄学”。GC日志是了解JVM内存行为的唯一窗口,不分析日志就直接改参数,就像闭着眼睛开车。
  4. 将GC问题归咎于JVM:很多时候,频繁的Full GC或者内存溢出(OOM)并非GC本身的问题,而是应用代码存在内存泄漏、对象创建过于频繁、对象生命周期过长等问题。GC只是个“背锅侠”。
  5. 过早优化:在应用上线前,或者在没有明确性能瓶颈的情况下,就花费大量时间进行GC调优,这是一种资源浪费。

最佳实践:

  1. 基准测试和GC日志分析先行

    • 首先,确保你的应用在稳定、有代表性的负载下运行。
    • 启用详细的GC日志:-Xlog:gc*(JDK 9+)或 -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/path/to/gc.log(JDK 8)。
    • 使用GCViewer、GCEasy等工具分析日志,关注以下指标:
      • GC停顿时间(Pause Time):单次停顿最长时间、平均停顿时间。
      • GC频率:Young GC、Old GC(Full GC)的发生频率。
      • 内存使用情况:GC前后堆内存的变化,是否存在内存泄漏趋势。
      • 晋升老年代的对象大小和频率
    • 找出GC瓶颈所在,是Young GC频繁导致停顿,还是Full GC导致长时间停顿。
  2. 从默认设置开始,逐步调整

    • JVM的默认GC设置通常对大部分应用都有不错的通用性。
    • 如果需要调优,从最关键的参数开始:
      • 堆内存大小-Xms -Xmx,通常设置成一样,避免运行时动态调整。
      • 新生代大小-Xmn-XX:NewRatio=。新生代太小容易频繁Young GC,太大可能导致老年代空间不足或Young GC停顿时间过长。
      • G1的最大停顿时间目标-XX:MaxGCPauseMillis=
      • CMS的并发GC触发阈值-XX:CMSInitiatingOccupancyFraction=
    • 每次只调整少量参数,观察效果,避免“一次性大改”。
  3. 关注代码层面的优化

    • 避免内存泄漏:例如,静态集合持有对象引用不释放、资源未关闭等。
    • 减少对象创建:尽量复用对象,减少临时对象的产生。使用对象池、享元模式等。
    • 合理使用数据结构:选择适合场景的数据结构,避免不必要的内存开销。
    • 避免大对象直接进入老年代:这会增加老年代GC的压力。
  4. 理解晋升老年代的机制

    • 对象在新生代经历多次Young GC仍存活,会晋升到老年代。
    • 大对象会直接进入老年代。
    • 新生代空间分配担保失败也会导致对象提前进入老年代。
    • 理解这些机制,有助于你调整新生代大小,减少老年代压力。

GC调优不是一蹴而就的,它是一个持续的、迭代的过程。关键在于“观察-分析-调整-验证”的循环。

为什么说理解垃圾收集器的工作原理对Java开发者至关重要?

作为一名Java开发者,如果对垃圾收集器一无所知,那就像是开着一辆高性能跑车,却不知道引擎盖下面藏着什么,更别提如何保养和维修了。理解GC的工作原理,在我看来,是提升你技术深度和解决实际问题能力的关键一环。

  1. 排查和解决性能瓶颈: 当你的应用出现卡顿、响应缓慢,或者CPU使用率飙高时,GC问题往往是首要排查对象之一。频繁的Full GC、长时间的STW,都可能导致服务不可用。如果你理解GC的原理,就能快速定位是新生代GC问题还是老年代GC问题,进而分析是内存泄漏、对象分配过快,还是GC配置不当。否则,你可能只能束手无策,或者盲目重启服务。

  2. 优化内存使用和应用设计: 理解GC会让你在编写代码时,自然而然地思考对象的生命周期、内存分配模式。你会更倾向于复用对象、减少临时对象的创建、避免不必要的内存占用。例如,如果你知道G1是分Region的,你可能会在设计时避免创建超大对象,以免它们直接进入老年代或巨型对象区,影响GC效率。这种“内存友好型”的编程习惯,能从根本上提升应用的健壮性和性能。

  3. 预测和避免内存溢出(OOM): OOM是Java应用中最常见的运行时错误之一。理解GC如何回收内存、内存分配失败的场景,能帮助你更好地预测何时可能发生OOM,并提前采取措施。例如,通过监控JVM的内存使用趋势,结合GC日志,你可以在内存耗尽前发现问题,而不是等到服务崩溃。

  4. 提升你的技术栈深度和面试竞争力: GC是JVM的核心组成部分,也是Java高级工程师面试中必考的知识点。对GC的深入理解,不仅能让你在面试中脱颖而出,更能证明你对Java生态系统有全面的把握,而不仅仅停留在API层面。这代表着你能够处理更复杂、更底层的技术挑战。

  5. 更好地理解和利用JVM的特性: JVM是一个复杂的运行时环境,GC只是其中一环。但GC的运作方式,与类加载、线程管理、即时编译等都有千丝万缕的联系。理解GC,能让你对整个JVM的运行机制有更深刻的认识,从而更好地利用JVM提供的各种特性和工具。

说白了,GC不是一个“黑盒”,它是一套精密的内存管理系统。作为开发者,我们有责任去了解它,驾驭它,让我们的应用跑得更快、更稳定。这不仅仅是技术上的挑战,更是我们对代码、对系统负责任的一种体现。

理论要掌握,实操不能落!以上关于《垃圾收集器有哪些?Serial、ParNew、CMS、G1、ZGC详解》的详细介绍,大家都掌握了吧!如果想要继续提升自己的能力,那么就来关注golang学习网公众号吧!

AO3官网2025最新入口地址公布AO3官网2025最新入口地址公布
上一篇
AO3官网2025最新入口地址公布
WooCommerce如何显示特色产品标签
下一篇
WooCommerce如何显示特色产品标签
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    499次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    484次学习
查看更多
AI推荐
  • PandaWiki开源知识库:AI大模型驱动,智能文档与AI创作、问答、搜索一体化平台
    PandaWiki开源知识库
    PandaWiki是一款AI大模型驱动的开源知识库搭建系统,助您快速构建产品/技术文档、FAQ、博客。提供AI创作、问答、搜索能力,支持富文本编辑、多格式导出,并可轻松集成与多来源内容导入。
    461次使用
  • SEO  AI Mermaid 流程图:自然语言生成,文本驱动可视化创作
    AI Mermaid流程图
    SEO AI Mermaid 流程图工具:基于 Mermaid 语法,AI 辅助,自然语言生成流程图,提升可视化创作效率,适用于开发者、产品经理、教育工作者。
    1241次使用
  • 搜获客笔记生成器:小红书医美爆款内容AI创作神器
    搜获客【笔记生成器】
    搜获客笔记生成器,国内首个聚焦小红书医美垂类的AI文案工具。1500万爆款文案库,行业专属算法,助您高效创作合规、引流的医美笔记,提升运营效率,引爆小红书流量!
    1277次使用
  • iTerms:一站式法律AI工作台,智能合同审查起草与法律问答专家
    iTerms
    iTerms是一款专业的一站式法律AI工作台,提供AI合同审查、AI合同起草及AI法律问答服务。通过智能问答、深度思考与联网检索,助您高效检索法律法规与司法判例,告别传统模板,实现合同一键起草与在线编辑,大幅提升法律事务处理效率。
    1273次使用
  • TokenPony:AI大模型API聚合平台,一站式接入,高效稳定高性价比
    TokenPony
    TokenPony是讯盟科技旗下的AI大模型聚合API平台。通过统一接口接入DeepSeek、Kimi、Qwen等主流模型,支持1024K超长上下文,实现零配置、免部署、极速响应与高性价比的AI应用开发,助力专业用户轻松构建智能服务。
    1346次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议隐私政策
返回登录
  • 重置密码