JVM垃圾收集器合集

devtools/2025/3/14 9:37:48/

前言:JVM GC收集器的回顾与比较

JVM(Java虚拟机)中的垃圾收集器是自动管理内存的重要机制,旨在回收不再使用的对象所占用的内存空间。以下是JVM中几种常见的垃圾收集器的详细介绍:

一、新生代垃圾收集器

  1. 1.Serial收集器
    • 类型:单线程收集器,新生代。
    • 特点:在垃圾收集时,会暂停所有其他工作线程(Stop-The-World),简单高效,发展历史最悠久。
    • 适用场景:适用于单核处理器环境和Client模式下的虚拟机。
‌Serial收集器是Java虚拟机(JVM)中最基本、历史最悠久的垃圾收集器之一‌。
它是一个单线程的垃圾收集器,这意味着它只会使用一个线程来完成垃圾收集工作。
Serial收集器在进行垃圾收集时,必须暂停其他所有的工作线程
(称为“Stop The World”,简称STW),直到垃圾收集结束。
这种设计虽然简单高效,但会导致应用在垃圾收集期间完全停顿,影响用户体验‌使用场景
Serial收集器主要用于客户端模式下的应用。由于客户端应用的内存通常较小,垃圾收集的时间较短,
只要不频繁发生停顿,这种设计是可以接受的。
此外,Serial收集器也是JDK 1.7及以前版本中Client模式下的默认新生代收集器‌优缺点
‌优点‌:‌简单高效‌:由于没有线程交互的开销,Serial收集器在单线程环境下可以获得较高的收集效率。
资源消耗少‌:对于限定单个CPU的环境来说,Serial收集器由于没有线程交互的开销,
专心做垃圾收集自然可以获得最高的单线程收集效率‌‌缺点‌:
‌停顿时间长‌:在进行垃圾收集时,必须暂停所有其他工作线程,导致应用完全停顿,影响用户体验‌
‌不适用于多核环境‌:在多核环境下,由于只有一个线程工作,无法充分利用多核处理器的优势‌
  1. 2.ParNew收集器
    • 类型:多线程收集器,新生代。
    • 特点:ParNew收集器是Serial收集器的多线程版本,除了使用多线程进行垃圾收集外,其余行为与Serial收集器相同。
    • 适用场景:适用于多核处理器环境。
‌ParNew是Java虚拟机(JVM)中的一个年轻代垃圾回收器,它是Serial收集器的多线程版本‌。
ParNew主要用于客户端应用或对响应时间敏感的应用程序,能够在多核处理器上发挥优势,
通过多线程并行处理垃圾回收工作,从而缩短Stop-The-World(STW)时间‌工作原理
ParNew的主要工作原理包括以下几点:
‌并行性‌:ParNew使用多线程同时执行垃圾收集工作,
这使得它能够在多核处理器上发挥优势,缩短STW时间‌
‌分代收集‌:ParNew只关注年轻代的垃圾回收,不处理老年代的垃圾回收。
当年轻代空间不足时,ParNew会被触发‌
‌复制算法‌:在年轻代中采用复制算法,将年轻代分为Eden区和两个Survivor区(S0和S1)。
垃圾收集时,所有存活的对象会被复制到另一个Survivor区或老年代,原来的Survivor区则被清空‌
‌对象晋升‌:经过几次垃圾回收后,存活的对象会被晋升到老年代,以减少年轻代的垃圾回收频率‌适用场景和优缺点
ParNew适用于以下场景:‌响应时间敏感的应用程序‌:由于ParNew的多线程特性,它能够在短时间内完成垃圾回收,
减少STW时间,适合交互式应用程序‌
‌服务器端大型系统‌:在多核CPU服务器上,ParNew能够充分发挥硬件优势,
提升回收效率,适用于高并发场景‌然而,ParNew也有一些局限性:
‌仅限于年轻代‌:ParNew不适用于整个堆的垃圾收集,只专注于年轻代‌
‌不适合高吞吐量应用‌:对于需要最大化CPU利用率的应用程序,ParNew可能不是最佳选择,
因为它的STW时间虽然较短,但总的垃圾收集时间可能较长‌
  1. 3.Parallel Scavenge收集器
    • 类型:多线程收集器,新生代。
    • 特点:追求高吞吐量,即CPU用于运行用户代码的时间与CPU总消耗时间的比值高。停顿时间越短越适合需要与用户交互的程序,而高吞吐量则可用高效率地利用CPU时间,尽快完成程序的运算任务。
    • 适用场景:主要适合在后台运算而不需要太多交互的任务。
‌Parallel Scavenge收集器是JVM(Java虚拟机)中的一个垃圾收集器,主要用于新生代垃圾收集,
采用标记-复制算法。‌Parallel Scavenge收集器是一款新生代收集器,主要关注垃圾收集的吞吐量。
吞吐量是指在一定时间内成功完成的工作量或任务的数量,即用户线程运行时间占总时间的比例。
Parallel Scavenge收集器通过多线程并行执行垃圾回收操作,提高吞吐量‌Parallel Scavenge收集器的特点
‌并行处理‌:Parallel Scavenge收集器可以并行处理垃圾回收任务,利用多线程提高垃圾收集的效率。
‌关注吞吐量‌:其主要目标是优化系统的整体吞吐量,减少垃圾收集对系统性能的影响。
‌参数调节‌:提供了-XX:MaxGCPauseMillis参数,用于控制最大垃圾回收停顿时间,
通过牺牲部分吞吐量来减少停顿时间‌Parallel Scavenge收集器的使用场景
Parallel Scavenge收集器适合那些对实时性要求不高,但需要高吞吐量的应用场景。
例如,科学数据计算、批量处理任务等。在这些场景下,虽然垃圾收集会占用一定的时间,
但总体上可以提高系统的处理效率‌

二、老年代垃圾收集器

  1. 1.Serial Old收集器
    • 类型:单线程收集器,老年代。
    • 特点:Serial Old是Serial收集器的老年代版本,使用标记整理算法。
    • 适用场景:适用于单核处理器环境和Client模式下的虚拟机。
‌Serial Old收集器是JVM中用于老年代的垃圾收集器‌。
它是Serial收集器的老年代版本,同样采用单线程工作方式,
并且在垃圾收集时需要暂停所有其他工作线程(用户线程),直到垃圾收集完成,
这个过程被称为“Stop The World”(STW)‌工作原理和特点
Serial Old收集器使用标记-压缩算法进行垃圾收集。它的主要用途包括:‌与Parallel Scavenge收集器搭配使用‌:在JDK 1.5及以前的版本中,
Serial Old与Parallel Scavenge搭配使用,主要用于服务器端应用。
‌作为CMS收集器的后备方案‌:在CMS收集器无法及时完成垃圾收集时,
Serial Old作为后备方案进行老年代的垃圾收集‌优缺点
‌优点‌:
‌简单高效‌:由于是单线程工作,实现简单,资源占用少。
‌适用于内存资源有限的环境‌:在客户端模式下,对于几十兆甚至一两百兆的新生代对象,
停顿时间可以控制在可接受范围内‌‌缺点‌:
‌停顿时间长‌:由于需要暂停所有工作线程,导致应用在垃圾收集期间完全停顿,
影响用户体验和应用程序的响应时间‌
  1. 2.Parallel Old收集器
    • 类型:多线程收集器,老年代。
    • 特点:Parallel Old是Parallel Scavenge收集器的老年代版本,使用多线程和“标记-整理”算法。
    • 适用场景:旨在提高系统吞吐量,适用于多线程环境。
‌Parallel Old收集器‌是JVM(Java虚拟机)中的一个垃圾收集器,主要用于老年代的垃圾收集。
它采用标记-压缩算法,并且是基于并行回收的机制。
Parallel Old收集器的主要特点是其高效的并行处理能力和对吞吐量的优化‌特点
‌并行回收‌:Parallel Old收集器使用多个线程进行垃圾收集,提高了垃圾收集的效率。
‌标记-压缩算法‌:它使用标记-压缩算法来减少内存碎片,提高内存利用率。
‌Stop-the-World机制‌:在进行垃圾收集时,Parallel Old收集器会暂停所有用户线程(Stop-the-World),直到垃圾收集完成。
使用场景
Parallel Old收集器通常用于需要高吞吐量的应用场景。
它通过减少垃圾收集的停顿时间来优化整体的应用性能,适合长时间运行的大规模应用‌
  1. 3.CMS(Concurrent Mark Sweep)收集器 类型
  • 定位:老年代并发收集器,需配合年轻代收集器(如ParNew)使用。

特点
  1. 目标:以降低停顿时间为核心目标,适合对延迟敏感的应用。

  2. 算法:采用**标记-清除(Mark-Sweep)**算法,非压缩式回收。

  3. 阶段划分

    • 初始标记(Initial Mark):标记GC Roots直接关联的老年代对象(需STW,时间短)。

    • 并发标记(Concurrent Mark):遍历老年代对象图(与用户线程并发)。

    • 重新标记(Remark):修正并发标记期间的变化(需STW,时间较长)。

    • 并发清除(Concurrent Sweep):清理垃圾对象(与用户线程并发)。

优点
  • 低停顿:通过并发标记和清除大幅减少STW时间。

  • 适合交互式应用:如Web服务器、实时交易系统等需快速响应的场景。

缺点
  1. CPU资源敏感

    • 并发阶段占用线程(默认启动(CPU_Cores + 3)/4个线程),在CPU核心数少(如≤4)时,可能导致应用吞吐量显著下降。

  2. 浮动垃圾(Floating Garbage)

    • 并发清理阶段用户线程可能产生新垃圾,若空间不足会触发Concurrent Mode Failure,退化为Serial Old收集器进行Full GC(长时间STW)。

  3. 内存碎片

    • 标记-清除算法不整理内存,长期运行后碎片化严重,可能导致:

      • 晋升失败(Promotion Failed):年轻代对象无法晋升到老年代。

      • 即使老年代总空间足够,因碎片无法分配大对象而触发Full GC。

  4. 内存预留要求

    • CMS需预留足够空间(通过-XX:CMSInitiatingOccupancyFraction设置触发阈值,默认92%),否则易触发并发失败。

  5. JDK版本兼容性

    • JDK 9+标记为废弃,JDK 14中正式移除,建议使用G1或ZGC替代。

适用场景
  • 低延迟需求:要求GC停顿时间控制在几百毫秒以内。

  • 中等堆内存(如4GB~8GB),且应用能容忍周期性Full GC。

  • CPU资源充足(建议≥4核),避免并发阶段争抢资源。

调优关键参数
参数默认值说明
-XX:+UseConcMarkSweepGC-启用CMS收集器
-XX:CMSInitiatingOccupancyFraction92%老年代使用率阈值触发CMS回收
-XX:+UseCMSCompactAtFullCollectiontrueFull GC时进行内存压缩(解决碎片问题,但增加停顿时间)
-XX:CMSFullGCsBeforeCompaction0执行多少次Full GC后触发压缩(0表示每次Full GC都压缩)
-XX:ParallelGCThreads-设置并发阶段的GC线程数(通常设为CPU核心数的25%~30%)
补充说明
  • 与Full GC的关系:CMS的失败(如Concurrent Mode Failure)会触发Serial Old收集器进行Full GC,导致长时间停顿。

  • 碎片问题缓解:可通过-XX:+UseCMSCompactAtFullCollection-XX:CMSFullGCsBeforeCompaction参数控制压缩频率,但会增加停顿时间。

  • 监控指标:需关注Concurrent Mode Failure次数、Full GC频率及耗时、老年代碎片率等。


总结

用户对CMS的描述基本正确,但需注意其已逐步被现代收集器(如G1、ZGC)取代,且存在内存碎片、并发失败等固有缺陷。在JDK 8及之前版本中,CMS仍适用于对延迟敏感的中等规模应用,但在新项目中建议优先考虑G1或低延迟的ZGC/Shenandoah。

‌CMS收集器(Concurrent Mark Sweep)是Java虚拟机(JVM)中的一种垃圾收集器,
主要用于老年代(Old Generation)的垃圾回收‌。
CMS收集器的目标是减少垃圾收集时的应用程序停顿时间(STW,Stop-The-World),
特别适用于对服务响应速度要求较高的场景,如互联网站或B/S系统的服务端Java应用‌工作原理
CMS收集器使用“标记-清除”算法,其工作过程主要包括以下几个阶段:‌初始标记‌:暂停所有其他线程,记录下GC Roots直接引用的对象。
‌并发标记‌:从GC Roots开始遍历整个对象图,这个过程可以与用户线程并发进行。
‌重新标记‌:修正并发标记期间因用户程序运行而导致的标记变化。
‌并发清理‌:开启用户线程,GC线程清理未标记的对象。
‌并发重置‌:重置本次GC过程中的标记数据‌特点
‌并发性‌:CMS设计为并发低停顿的垃圾收集器,使得在垃圾回收过程中用户线程不会停顿或停顿时间很短,
有助于保障系统的响应速度‌‌标记-清除算法‌:CMS使用标记-清除算法进行垃圾回收,
这种算法在处理过程中需要多次暂停用户线程以确保准确性‌‌适用场景‌:由于CMS收集器能有效减少停顿时间,特别适合那些对用户体验要求较高的应用场景,
如服务器端应用和需要高并发处理的系统‌

三、兼顾新生代和老年代的垃圾收集器 G1收集器

  1. G1(Garbage-First)收集器

    • 类型:并行与并发收集器,适用于新生代和老年代。
    • 特点
      • 并行与并发‌:G1收集器能够充分利用多核处理器的优势,通过并行执行垃圾收集任务来提高效率。同时,它的大部分工作都是与应用线程并发执行的,从而减少了停顿时间‌。
      • 分区域收集‌:G1将整个堆内存划分为多个大小相等的独立区域(Region),这些区域在逻辑上是连续的,但在物理内存上可能不是连续的。每个Region都可以扮演Eden区、Survivor区或Old区等角色。这种设计使得G1 GC能够更加灵活地进行内存管理和垃圾收集‌。
      • 优先回收垃圾最多区域‌:G1通过跟踪每个Region中的垃圾堆积情况,并根据回收价值和成本进行排序,优先回收垃圾最多的Region。这种策略有助于最大限度地提高垃圾收集的效率‌。
      • 可预测的停顿时间‌:G1通过建立一个可预测的停顿时间模型,允许用户明确指定在一个特定时间片段内,垃圾收集所造成的停顿时间不得超过某个阈值。这使得G1非常适合需要严格控制停顿时间的应用场景‌。
    • 适用场景:面向服务端应用,能充分利用多CPU、多核环境,适用于需要低延迟和可预测停顿时间的大型应用程序。
    • 适合大堆内存

      • G1通过 Region分区机制(默认2048个分区)有效管理大内存堆(4GB~数十GB),规避传统分代GC的全堆扫描问题。

      • 实际应用案例:在16GB以上堆内存场景中,G1的 平均停顿时间 通常比CMS低30%~50%。

    • 简化调优

      • 核心参数确实聚焦于:

        • -Xms/-Xmx(堆初始/最大值)

        • -XX:MaxGCPauseMillis(目标最大停顿时间,默认200ms)

      • 例如,仅设置以下参数即可获得较好表现:

        -XX:+UseG1GC -Xms8g -Xmx8g -XX:MaxGCPauseMillis=150
    • Garbage First设计原则

      • G1通过 回收效益优先模型(Predictive Model),优先回收垃圾比例高(Garbage-First)的Region,确保内存利用率合理。

      • 统计表明,G1的 空间释放效率 比CMS高15%~25%,尤其适合对象生命周期差异大的场景。

    • 进阶调优场景

      • Region大小调整-XX:G1HeapRegionSize):影响大对象分配和回收粒度。

      • 并发线程数-XX:ConcGCThreads):控制并发标记阶段的吞吐量。

      • 混合回收策略-XX:G1MixedGCCountTarget):调整Old Region回收比例。

      • 示例调优参数

        -XX:G1HeapRegionSize=16m \
        -XX:ConcGCThreads=4 \
        -XX:G1MixedGCLiveThresholdPercent=85
    • G1收集器的历史背景和替代CMS收集器

      G1收集器在JDK 7u4版本中被正式推出,并在JDK 9中成为默认的垃圾收集器。它取代了CMS收集器,后者在JDK 9中被废弃,并在JDK 14中被完全移除。G1的设计目的是为了适应不断扩大的内存和增加的处理器数量,进一步降低暂停时间,同时兼顾良好的吞吐量‌

    • 总结:G1是一款面向大堆内存的垃圾收集器,通过Region分区和Garbage-First策略实现低停顿目标。其调优参数简单直观(堆大小和最大暂停时间),但需注意元数据内存开销。在JDK 11+中,G1通过算法优化显著提升了吞吐量和稳定性,成为多数场景的默认选择

性能数据参考

指标G1(JDK 17)CMS(JDK 8)ZGC(JDK 17)
最大堆内存支持16TB16GB16TB
平均停顿时间(ms)50~200100~3001~10
吞吐量损失5%~10%10%~20%<5%
内存开销中等

参考:详解 JVM Garbage First(G1) 垃圾收集器-腾讯云开发者社区-腾讯云


http://www.ppmy.cn/devtools/166988.html

相关文章

【Crypto】CTF 密码学题目解题思路图

CTF密码学题目解题思路图 密码学题目 ├── 1. 编码/转换 │ ├── 1.1 Base64 │ │ └── 步骤&#xff1a;检查填充字符&#xff08;&#xff09;&#xff0c;解码工具&#xff08;CyberChef&#xff09;。 │ ├── 1.2 Hex │ │ └── 步骤&#xff1a…

C++蓝桥杯基础篇(十一)

片头 嗨~小伙伴们&#xff0c;大家好&#xff01;今天我们来学习C蓝桥杯基础篇&#xff08;十一&#xff09;&#xff0c;学习类&#xff0c;结构体&#xff0c;指针相关知识&#xff0c;准备好了吗&#xff1f;咱们开始咯~ 一、类与结构体 类的定义&#xff1a;在C中&#x…

打造流畅的下拉刷新与轮播交互:HarmonyOS手势识别与组件协同实战

打造流畅的下拉刷新与轮播交互&#xff1a;HarmonyOS手势识别与组件协同实战 在现代移动应用开发中&#xff0c;流畅且自然的交互体验是提升用户满意度的关键因素之一。下拉刷新和轮播组件是许多应用中常见的功能&#xff0c;但如何让它们在手势操作中无缝协同工作&#xff0c…

智能三防手持终端破解传统仓储效率困局

在数字化浪潮的推动下&#xff0c;传统仓储管理模式正面临效率低、成本高、错误频发等瓶颈。如何实现精准、高效、智能化的仓储管理&#xff0c;上海岳冉三防智能手持终端机以RFID技术为核心&#xff0c;结合工业级三防&#xff08;防水、防摔、防尘&#xff09;设计&#xff0…

内检实验室lims系统在电子设备制造行业的应用

在电子设备制造行业&#xff0c;内检实验室LIMS&#xff08;实验室信息管理系统&#xff09;的应用正变得日益重要。随着技术的不断进步和行业标准的提高&#xff0c;传统的手工记录和管理方式已难以满足现代电子制造业的需求。LIMS系统通过整合多种功能和技术&#xff0c;为电…

2019年蓝桥杯第十届CC++大学B组真题及代码

目录 1A&#xff1a;组队&#xff08;填空5分_手算&#xff09; 2B&#xff1a;年号字符&#xff08;填空5分_进制&#xff09; 3C&#xff1a;数列求值&#xff08;填空10分_枚举&#xff09; 4D&#xff1a;数的分解&#xff08;填空10分&#xff09; 5E&#xff1a;迷宫…

React Next项目中导入Echart世界航线图

公司业务要求做世界航线图&#xff0c;跑了三个ai未果&#xff0c;主要是引入world.json失败&#xff0c;echart包中并不携带该文件&#xff0c;源码的world.json文件页面404找不到。需要自己寻找。这是整个问题卡壳的关键点&#xff0c;特此贴出资源网址。 一、安装 npm inst…

13. Pandas :使用 to_excel 方法写入 Excel文件

一 to_excel 方法的相关参数 用它来指定要将 DataFrame 写入哪些工作表的哪些单元格&#xff0c;以及是否需要包含列标题和 DataFrame 索引。如何处理特殊值&#xff08;如 np.nan 和 np.inf&#xff09;。 1.指定工作表和单元格 sheet_name&#xff1a;指定将 DataFrame 写入的…