在JVM内存体系中,堆内存的“分代结构”与“对象流转规则”是通用基础,但垃圾回收器(GC)是决定堆内存实际表现的核心变量——不同GC为实现“低延迟”“高吞吐量”等目标,会对堆的划分方式、对象管理逻辑、参数配置规则进行定制化改造。

本文作为JVM内存结构系列的第四篇,将以“堆内存”为纽带,系统拆解经典分代GC、G1
GC、非分代GC
与堆的适配差异,帮你理解“堆的理论模型”如何在实际GC中落地,避免在调优时混淆“通用堆参数”与“GC专属逻辑”,同时为后续实战篇(GC问题排查)铺垫核心认知。

一、核心认知:GC与堆的适配本质——“目标决定结构”

在分析具体GC前,需先明确一个核心逻辑:GC对堆的改造,本质是为了匹配自身的设计目标。不同GC的目标差异,直接导致了堆内存管理方式的分化:

  • 追求“高吞吐量”的GC(如Parallel Scavenge):会尽量简化堆管理逻辑,减少GC线程与用户线程的交互开销;
  • 追求“低延迟”的GC(如CMS、ZGC):会通过复杂的堆划分(如Region、Page)和并发回收机制,缩短用户线程暂停(STW)时间;
  • 平衡“延迟与吞吐量”的GC(如G1):会采用动态化的堆管理策略,在两者间找到最优解。

后续所有GC与堆的适配细节,都围绕这个逻辑展开。

二、经典分代GC:严格遵循堆分代模型,适配中小堆内存

经典分代GC是JVM早期的主流选择,其核心特点是完全遵循“年轻代+老年代”的物理分代模型,仅在“回收线程数”“老年代算法”上存在差异,适合堆内存≤4GB的场景(如单体应用、小型微服务)。

代表GC组合:SerialGC(Serial+Serial Old)、ParNew+CMS、Parallel Scavenge+Parallel Old。

2.1 与堆的适配共性:年轻代管理逻辑统一

所有经典分代GC的年轻代管理逻辑完全一致,均基于“复制算法”实现高效回收,具体适配细节如下:

  • 堆划分规则:年轻代严格按“Eden:Survivor=8:1:1”划分(可通过-XX:SurvivorRatio调整),老年代占堆总大小的2/3,物理上与年轻代连续;
  • 对象分配与晋升
    1. 新对象(非大对象)优先分配到Eden区,大对象(超过-XX:PretenureSizeThreshold)直接进入老年代;
    2. Minor GC时,Eden区存活对象复制到To Survivor,From Survivor存活对象按“年龄计数器”判断:未达阈值(默认15,-XX:MaxTenuringThreshold)则复制到To Survivor,达标则晋升到老年代;
    3. 支持“动态年龄判断”(-XX:TargetSurvivorRatio),Survivor区同年龄对象占比超阈值时,该年龄及以上对象提前晋升。
  • 回收线程特性:差异仅体现在“回收线程数”——SerialGC用单线程回收年轻代,ParNew和Parallel Scavenge用多线程回收(ParNew线程数与CPU核心数绑定,Parallel Scavenge可通过-XX:ParallelGCThreads调整)。

2.2 与堆的适配差异:老年代算法决定堆特性

经典分代GC的核心差异集中在老年代回收算法上,而算法选择直接决定了老年代的“内存碎片情况”“大对象分配安全性”和“Full GC耗时”,最终影响堆的整体表现:

老年代GC组合核心算法堆内存特性(老年代)适配场景关键堆参数差异
Serial+Serial Old标记-整理(Mark-Compact)内存连续,无碎片;大对象分配安全;但Full GC单线程执行,耗时久(百毫秒~秒级)堆内存小(≤2GB)、低并发场景(如本地测试、轻量工具)无特殊参数,依赖-Xms/-Xmx控制堆大小
ParNew+CMSCMS:标记-清除(Mark-Sweep)
Serial Old:标记-整理(备用)
内存有碎片(标记-清除算法导致);大对象可能因无连续空间触发Full GC;CMS并发回收,Full GC(CMS失败时触发)耗时久堆内存中等(2GB~4GB)、低延迟优先场景(如Web服务)-XX:CMSFullGCsBeforeCompaction:设置多少次CMS后执行整理(默认0,即每次CMS后整理,减少碎片)
Parallel Scavenge+Parallel OldParallel Old:标记-整理(Mark-Compact)内存连续,无碎片;大对象分配安全;多线程回收老年代,Full GC耗时比Serial Old短堆内存中等(2GB~4GB)、高吞吐量优先场景(如数据处理、批量任务)-XX:MaxGCPauseMillis:动态调整年轻代大小(缩小年轻代减少Minor GC耗时);-XX:GCTimeRatio:控制GC时间占比(默认99,即GC时间≤1%)

2.3 经典分代GC的堆适配局限

随着堆内存增大(超过4GB),经典分代GC的局限逐渐凸显:

  • 物理分代导致的回收范围固定:Minor GC仅回收年轻代,Full GC回收全堆,堆越大Full GC耗时越长,无法灵活选择回收区域;
  • 碎片问题(CMS):标记-清除算法导致老年代碎片累积,需频繁执行整理操作(增加STW时间);
  • 参数依赖强:需手动调整年轻代比例、晋升阈值等参数,堆越大调优难度越高。

三、G1 GC:打破物理分代,堆内存的“Region化”改造

为解决经典分代GC在大堆内存(≥8GB)下的局限,G1 GC(Garbage-First GC)采用了Region化堆布局,通过“动态分代”和“优先回收垃圾多的区域”实现“低延迟+高吞吐量”的平衡,适合大型微服务、电商核心服务等场景。

3.1 堆布局革命:从“物理分代”到“Region动态角色”

G1 GC彻底打破了“年轻代与老年代物理连续”的传统结构,将堆内存划分为2048个大小相等的Region(每个Region大小1MB~32MB,通过-XX:G1HeapRegionSize设置,需为2的幂次方),每个Region动态扮演不同角色:

  • 年轻代Region:包括Eden Region和Survivor Region,逻辑上属于年轻代,物理上分散在堆中;
  • 老年代Region:存放从年轻代晋升的对象,物理上与年轻代Region混杂;
  • 大对象Region(Humongous Region):专门存储“大对象”(大小超过Region的50%),由连续多个Region组成,逻辑上属于老年代。

这种布局的核心优势:GC可灵活选择部分Region回收(而非全堆),大幅缩短STW时间

3.2 与堆的适配细节:动态化的对象管理逻辑

G1 GC对堆的管理逻辑完全围绕“Region”展开,与经典分代GC差异显著:

3.2.1 年轻代管理:逻辑保留,物理动态
  • 年轻代Region的动态调整:G1没有固定的年轻代大小(经典分代GC年轻代占堆1/3),而是根据“最大暂停时间目标”(-XX:MaxGCPauseMillis,默认200ms)动态调整年轻代Region数量——若Minor GC耗时超过目标,会减少年轻代Region;若年轻代过小导致晋升频繁,会增加年轻代Region。
  • Minor GC流程:仅回收所有年轻代Region(Eden+Survivor),存活对象复制到新的Survivor Region或直接晋升到老年代Region,回收后清空原年轻代Region(无碎片)。
3.2.2 老年代管理:优先回收“垃圾多的Region”

G1的“Garbage-First”得名于其回收策略:每次GC优先选择“垃圾占比高的Region”(老年代Region为主),具体逻辑:

  • Mixed GC(混合回收):当老年代Region占比超过“阈值”(-XX:InitiatingHeapOccupancyPercent,默认45%),触发Mixed GC——同时回收所有年轻代Region和部分“垃圾占比高的老年代Region”,避免Full GC(G1尽量避免Full GC,Full GC时会退化为Serial Old算法,耗时极长)。
  • 老年代Region的晋升规则:无固定“年龄阈值”(经典分代GC默认15),G1通过“Region的存活对象占比”判断——若Survivor Region的存活对象占比低,直接晋升为老年代Region;若占比高,则继续作为Survivor Region保留。
3.2.3 大对象处理:Humongous Region的特殊逻辑
  • 分配规则:对象大小超过Region的50%时,直接分配到连续的Humongous Region,避免在普通Region中频繁复制;
  • 回收时机:Humongous Region的回收与老年代Region同步(仅在Mixed GC或Full GC时回收),需注意:频繁创建大对象会导致Humongous Region堆积,快速触发Mixed GC,甚至Full GC(如频繁创建100MB对象,Region大小设为32MB,则每个大对象占用4个Humongous Region)。

3.3 G1 GC的核心堆参数(与经典分代GC的差异)

G1 GC的参数设计更聚焦“目标控制”(如暂停时间),而非“分代比例”,核心堆相关参数如下:

参数名默认值核心作用(与堆适配相关)调优场景示例
-XX:G1HeapRegionSize自动计算(堆≤4GB时1MB,堆≤8GB时2MB,以此类推)设置单个Region大小,决定大对象阈值(Region大小的50%)若应用频繁创建大对象(如50MB),可设为-XX:G1HeapRegionSize=32M(大对象阈值16MB,50MB对象需2个Region,减少Region数量)
-XX:MaxGCPauseMillis200ms控制GC最大暂停时间,G1会动态调整年轻代Region数量适配该目标低延迟场景(如支付服务)设为-XX:MaxGCPauseMillis=100,减少单次GC耗时
-XX:InitiatingHeapOccupancyPercent45%触发Mixed GC的老年代Region占比阈值若堆内存大(如32GB),可提高至-XX:InitiatingHeapOccupancyPercent=60,减少Mixed GC频率
-XX:G1MixedGCCountTarget8控制Mixed GC回收老年代Region的次数(默认8次内回收完符合条件的老年代Region)若老年代Region堆积快,可降低至-XX:G1MixedGCCountTarget=4,加快老年代回收

四、非分代GC:彻底抛弃分代模型,堆内存的“统一管理”

对于超大堆内存(≥64GB,如大数据、AI服务),“分代模型”已无法满足“极致低延迟”(GC暂停≤10ms)的需求——非分代GC(ZGC、Shenandoah)彻底抛弃分代逻辑,采用“全堆统一管理+并发回收”,实现TB级堆内存的高效管理。

4.1 堆布局:无分代,仅按“内存单元”划分

非分代GC的堆布局极度简化,无“年轻代/老年代”概念,仅按固定大小的“内存单元”划分:

  • ZGC(Z Garbage Collector):将堆分为Page(页面),Page大小分三类:小页面(2MB,存小对象)、中页面(32MB,存中对象)、大页面(≥2GB,存大对象),大页面无需连续,直接映射物理内存;
  • Shenandoah GC:与G1类似,将堆分为Region(默认1MB),无动态分代角色,所有Region地位平等,大对象直接存放在连续Region中。

这种布局的核心优势:GC可并发回收全堆(无需区分年轻代/老年代),STW时间仅与“对象引用遍历”相关,与堆大小无关(ZGC堆从8GB扩容到1TB,STW时间仍保持在10ms内)。

4.2 与堆的适配细节:并发回收与无碎片管理

非分代GC的堆管理逻辑围绕“并发”和“无碎片”设计,彻底解决了大堆内存下的延迟问题:

4.2.1 ZGC:基于“着色指针”的并发回收
  • 核心技术:着色指针:ZGC通过“指针编码”(在64位指针中嵌入3位标记位)标记对象状态(如“可回收”“正在迁移”),无需暂停用户线程即可完成对象标记;
  • 堆内存特性
    1. 无碎片:采用“标记-复制”算法,回收时将存活对象复制到新Page,原Page清空后复用,堆内存始终连续;
    2. 大对象友好:大页面(≥2GB)直接映射物理内存,无需复制(仅标记回收),支持TB级大对象;
    3. 无分代参数:无需配置“年轻代比例”“晋升阈值”,仅需通过-XX:ZHeapSize设置堆大小(初始=最大,避免扩容)。
4.2.2 Shenandoah GC:基于“读屏障”的并发整理
  • 核心技术:读屏障:Shenandoah在用户线程读取对象引用时插入“屏障”,记录引用访问,实现并发标记和并发整理;
  • 堆内存特性
    1. 无碎片:采用“标记-整理”算法(并发整理,无需复制对象),直接在原Region中移动对象,整理后内存连续;
    2. 回收效率高:全堆并发回收,STW时间仅用于“初始标记”和“最终标记”(各约1ms);
    3. 堆参数简单:通过-XX:ShenandoahHeapRegionSize设置Region大小(默认1MB),-XX:ShenandoahGCHeuristics选择回收策略(如“低延迟优先”“吞吐量优先”)。

4.3 非分代GC的堆适配优势与局限

优势局限
1. 堆大小无关性:STW时间不随堆增大而增加,支持TB级堆;
2. 无碎片:无需担心大对象分配失败;
3. 参数简单:无需手动调整分代参数,调优成本低;
4. 极致低延迟:GC暂停≤10ms,适合对延迟敏感的超大堆场景(如AI训练、实时数据分析)。
1. 线程开销高:着色指针(ZGC)和读屏障(Shenandoah)会增加用户线程开销(约5%~10%);
2. JDK版本依赖:ZGC在JDK11正式发布,Shenandoah在JDK12正式发布,需升级JDK版本;
3. 工具支持:部分监控工具(如早期JVisualVM)对非分代GC的指标展示不完善。

五、实战选型:根据堆内存特性匹配GC

掌握GC与堆的适配关系后,核心目标是“根据堆内存大小、应用目标(延迟/吞吐量)选择合适的GC”,以下是实战选型指南:

堆内存规模核心目标推荐GC堆适配关键注意事项
≤4GB低并发、简单场景SerialGC无需复杂参数,堆大小设为-Xms2G -Xmx2G即可,避免频繁扩容
4GB~8GB高吞吐量(如批量任务)Parallel Scavenge+Parallel Old依赖-XX:MaxGCPauseMillis动态调整年轻代,避免手动设置-XX:MaxNewSize
4GB~8GB低延迟(如Web服务)ParNew+CMS需配置-XX:CMSFullGCsBeforeCompaction=3(3次CMS后整理碎片),避免大对象堆积
8GB~64GB低延迟+高吞吐量(如电商核心服务)G1 GC1. 设-XX:G1HeapRegionSize=16M(堆32GB时);
2. 控制-XX:MaxGCPauseMillis=100
3. 避免频繁创建超过Region 50%的大对象
≥64GB极致低延迟(如AI训练、实时数据)ZGC/Shenandoah1. ZGC设-XX:ZHeapSize=64G(初始=最大);
2. Shenandoah设-XX:ShenandoahGCHeuristics=latency(低延迟优先);
3. 确保JDK版本≥11(ZGC)/12(Shenandoah)

六、小结与预告:GC与堆的联动是调优核心

本文通过“经典分代GC→G1 GC→非分代GC”的递进逻辑,解析了GC与堆内存的适配本质:

  1. 经典分代GC是“堆分代模型的严格实现”,适合中小堆,核心差异在老年代算法;
  2. G1 GC是“堆Region化的过渡方案”,通过动态分代平衡延迟与吞吐量,适合大堆;
  3. 非分代GC是“堆统一管理的终极形态”,通过并发回收实现极致低延迟,适合超大堆。

理解这种适配关系,是后续GC调优和内存问题排查的关键——比如“G1的Humongous Region堆积导致OOM”“CMS的老年代碎片导致Full GC频繁”等问题,本质都是“GC特性与堆内存使用不匹配”。

下一篇(系列第五篇),我们将聚焦《JVM方法区与元空间:从永久代到元空间的变迁》,解析堆外的“类信息存储区域”,以及它与堆内存、GC的关联逻辑,进一步完善JVM内存结构的认知框架。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/94173.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/94173.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/94173.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Zemax光学设计输出3D

输出立体数据文件(IGES/STEP/SAT/STL 格式)的参数设置界面,各参数含义如下:1. 起始面/终止面:设定要输出立体数据对应的光学表面范围,从第 0 个表面到第 9 个表面 ,限定参与输出的光学结构表面区…

模块测试与低功耗模式全攻略

一、模块测试流程在测试一个模块时,建议遵循以下步骤:基本测试:测试该模块的寄存器读写功能是否正常。可以向每个寄存器写入 0x5A5A 和 0xA5A5,这两种模式可以覆盖对寄存器写入 0 和 1 的情况。进阶测试:在基本测试通过…

机器学习实验三、使用决策树算法预测泰坦尼克号幸存者

实验目的1. 掌握特征工程,会进行特征提取与特征选择,会进行缺失值填充。2. 建立决策树模型,解决实际问题。3. 会对模型进行调试,能够绘制并保存决策树。实验环境Python 3.7.0,Sklearn ,PyCharm实验原理1、特…

从全栈开发到微服务架构:一次真实的Java面试实录

从全栈开发到微服务架构:一次真实的Java面试实录 面试官与应聘者介绍 面试官:李明,某互联网大厂技术负责人,擅长Java后端、微服务及云原生架构。 应聘者:张伟,28岁,硕士学历,拥有5年…

新的 Gmail 网络钓鱼攻击利用 AI 提示注入来逃避检测

网络钓鱼一直以来都是为了欺骗人们。但在这次活动中,攻击者不仅瞄准用户,还试图操纵基于人工智能的防御系统。 这是我上周记录的Gmail 网络钓鱼链的演变。那次攻击活动依赖于紧迫性和重定向,但这次引入了隐藏的 AI 提示,旨在混淆…

Restful风格设计

文章目录什么是Restful风格?RESTful API设计最佳实践1. URL设计原则2. HTTP状态码的正确使用3. 统一的响应格式实际案例:用户管理系统API总结什么是Restful风格? 我的理解是:Restful是一种基于HTTP协议的架构设计风格&#xff0c…

深入 Glide 图像变换:自定义效果、GIF处理与组合变换

在 Android 开发中,Glide 的强大不仅在于其高效的加载和缓存能力,更在于其无与伦比的可扩展性,尤其是在图像处理层面。当内置的 fitCenter() 和 circleCrop() 无法满足你的设计需求时,自定义 Transformation 便是你的终极武器。本…

数据挖掘 4.8 评估泛化能力

4.8 Estimating Generalization 4.8 评估泛化能力 评估模型的泛化能力如何合理评估模型的泛化能力指导原则 (Guidelines)存在的问题 (Issues)K-fold 交叉验证(Cross-Validation)留一交叉验证(Leave One Out CV)(LOOCV)Stratification 分层训练…

46.【.NET8 实战--孢子记账--从单体到微服务--转向微服务】--扩展功能--集成网关--网关集成日志

本篇文章,我们一起在网关中集成日志功能,我们要在网关中记录下游微服务出现的异常信息、请求信息以及响应信息。在微服务架构中,网关作为系统的入口,承担着非常重要的职责。通过在网关层面集成日志功能,我们可以更好地…

使用 FastAPI 的 WebSockets 和 Elasticsearch 来构建实时应用

作者:来自 Elastic Jeffrey Rengifo 学习如何使用 FastAPI WebSockets 和 Elasticsearch 构建实时应用程序。 更多阅读:使用 FastAPI 构建 Elasticsearch API 想要获得 Elastic 认证吗?看看下一次 Elasticsearch Engineer 培训什么时候开始&…

华为云ModelArts+Dify AI:双剑合璧使能AI应用敏捷开发

引言:AI应用开发的敏捷化转型需求 随着大语言模型(LLM)技术的迅猛发展,企业与开发者对AI应用开发的敏捷化转型需求日益凸显,亟需将大模型能力快速转化为实际业务价值。传统AI开发模式中,复杂的模型工程化、流程编排和部署维护工作往往需要专业技术团队支撑,典型痛点包括…

网络实践——Socket编程UDP

文章目录Socket编程UDPUDP接口的使用铺垫socketrecvform && sendtobind字节序转化使用(Tips)实践部分version_1echo_serverversion_2dict_serverversion_3chat_serverSocket编程UDP 在了解了相关的网络基础知识后,我们不会像学系统知识一样,先学…

GD32 波形发生器,三角波,正弦波,方波。AD9833+MCP410生成和MCU自身的DAC生成。波形,频率,振幅可以通过按键和OLED调整输出。

DIY一个简易的信号发生器驱动板,主要是三角波和正弦波,方波。主板有两个通道能输出波形,CH0由AD9833MCP410AD8051放大电路组成,理论可以生成0.1-12.5MHZ的频率信号,单电源振幅范围是1-9V。CH1由MCU外设DAC生成的信号&a…

VS2022的MFC中关联使用控制台并用printf输出调试信息

前言 MFC一般在调试的时候,可以在IDE中方便的看到调试的信息。但是,有时候运行的时候也要看调试的信息怎么办?最好如同在Console(控制台)程序中输出一般的方便,可以么?可以的。 一、设置 1.1、加…

ZKmall模块商城的推荐数据体系:从多维度采集到高效存储的实践

在电商领域,个性化推荐已成为提升用户体验与转化效率的核心手段。ZKmall 模块商城基于用户行为、商品属性与交易数据,构建了一套完整的推荐算法体系,而数据采集的全面性与存储的高效性是该体系的基础。本文将聚焦推荐算法的 “数据输入端”&a…

Qt + windows+exe+msvc打包教程

目录 1. Qt + windows+exe+msvc打包教程1 1.1. Enigma Virtual Box下载⏬1 1.2. Enigma Virtual Box安装2 1.3. Qt 打包成独立exe教程6 1.3.1. Qt项目创建6 1.3.2. Qt项目编译13 1.3.3. Qt 项目打包 windeployqt命令14 1.3.4. Qt 项目打包 Enigma Virtual Box工具18 Q…

大语言模型应用开发——利用OpenAI函数与LangChain结合从文本构建知识图谱搭建RAG应用全流程

概述 从文本等非结构化数据中提取结构化信息并非新鲜事物,但大语言模型(LLMs)为该领域带来了重大变革。以往需要机器学习专家团队策划数据集并训练自定义模型,如今只需访问LLM即可实现,显著降低了技术门槛&#xff0c…

Vue3+Spring Boot技术栈,前端提交混合表单数据(普通字段+文件字段),上传文件,后端插入数据,将文件保存到数据库

一、技术栈1、前端 Vue3 Element Plus TypeSprict2、后端 Spring Boot 3.2.12 Mybatis Plus3、模型特点3.1、表格展示列表数据3.2、行点击,弹出对话框3.3、前端使用 FormData 提交混合表单数据,包含普通字段和文件字段3.4、文件对应数据库结构类型为 …

【Qt开发】Qt的背景介绍(四)

目录 1 -> Qt Hello World 程序 1.1 -> 使用“按钮”实现 1.1.1 -> 纯代码方式实现 1.1.2 -> 可视化操作实现 1.2 -> 使用“标签”实现 1.2.1 -> 纯代码方式实现 1.2.2 -> 可视化操作实现 2 -> 项目文件解析 2.1 -> .pro文件解析 2.2 -&g…

Linux驱动开发笔记(六)——pinctrl GPIO

开发板:imx6ull mini 虚拟机:VMware17 ubuntu:ubuntu20.04 视频:第8.1讲 pinctrl和gpio子系统试验-pincrl子系统详解_哔哩哔哩_bilibili 文档:《【正点原子】I.MX6U嵌入式Linux驱动开发指南.pdf》四十五章 这一章…