Garbage First - Card Table

本文通过探讨CardTable在GarbageFirst垃圾回收器中的应用,为读者提供了对该技术的深入了解。文章揭示了CardTable如何帮助提升垃圾回收效率。

之前一直以为只是在Garbage First垃圾回收器中,有Card Table,终于在这篇文章中有些提示,让我对Card Table的作用有了清晰的认识,对Garbage First基本上有所了解了,应该可以进行总结了。。。。。。

 

http://vrlinux.com/wenzhangjingxuan/20101115/79907_2.html

http://www.blogjava.net/BlueDavy/archive/2009/03/11/259230.html

<think>我们正在讨论G1垃圾回收器(Garbage-First)的工作原理和调优参数。根据引用内容,G1是在Java7 update4之后引入的,旨在降低暂停时间的同时兼顾高吞吐量,适用于大内存和多处理器的场景。下面我将详细解释G1的工作机制和常用调优参数。 ### 一、G1垃圾回收器的工作原理 G1是一种面向服务端应用的垃圾回收器,它采用分区的思想,将整个堆空间划分为多个大小相等的区域(Region)。这些区域可以是Eden区、Survivor区、Old区或Humongous区(用于存放大对象)。G1通过可预测的停顿模型,允许用户设置期望的停顿时间目标(如`-XX:MaxGCPauseMillis`),并尽力在该时间内完成垃圾回收。 #### 1. **内存布局** - **区域(Region)**:堆被划分为多个Region,每个Region的大小在1MB到32MB之间,且必须是2的幂。Region的大小可以通过`-XX:G1HeapRegionSize`设置。 - **区域类型**: - **Eden Regions**:新对象分配的区域。 - **Survivor Regions**:存放年轻代GC后存活的对象。 - **Old Regions**:存放长时间存活的对象。 - **Humongous Regions**:存放大小超过Region一半的大对象,连续分配。 #### 2. **垃圾回收过程** G1的垃圾回收过程分为两个阶段:**年轻代GC(Young GC)**和**混合回收(Mixed GC)**。 - **年轻代GC(Young GC)**: - 当Eden区满时触发,只回收Eden区和Survivor区。 - 采用复制算法,将存活对象复制到新的Survivor区或晋升到Old区。 - 该过程需要STW(Stop-The-World),但时间较短。 - **混合回收(Mixed GC)**: - 当堆内存使用达到一定阈值(由`-XX:InitiatingHeapOccupancyPercent`设置,默认45%)时触发。 - 回收范围包括整个年轻代和部分老年代(根据预测选择回收价值最高的Region,即垃圾最多的Region,这也是“Garbage-First”名称的由来)。 - 同样采用复制算法,将存活对象复制到空闲Region。 - 混合回收可能分多次进行,每次回收一部分Region,以控制停顿时间。 - **Full GC**: - 当混合回收速度跟不上对象分配速度,或者无法找到足够的空闲Region时,会触发Full GC(单线程的Serial Old GC),此时停顿时间会很长。因此,应尽量避免Full GC。 #### 3. **核心算法** - **SATB(Snapshot-At-The-Beginning)**: - G1使用SATB算法处理并发标记阶段的漏标问题。它在标记开始时对堆内存做快照,确保标记过程中新分配的对象不会被遗漏。 - **RSet(Remembered Set)**: - 每个Region都有一个RSet,用于记录其他Region中的对象对本Region的引用。这样在回收某个Region时,无需扫描整个堆,只需扫描RSet即可确定跨代引用。 #### 4. **工作流程** 1. **初始标记(Initial Mark)**:标记从GC Roots直接可达的对象,伴随一次Young GC,STW。 2. **并发标记(Concurrent Marking)**:从GC Roots开始进行可达性分析,找出存活对象,与用户线程并发执行。 3. **最终标记(Final Marking)**:处理SATB缓冲区,修正并发标记期间变动的引用,STW。 4. **筛选回收(Evacuation)**:根据回收价值和停顿时间要求,选择Region进行回收(复制存活对象),STW。 ### 二、G1常用调优参数 | **参数** | **默认值** | **说明** | |----------|------------|----------| | `-XX:+UseG1GC` | - | 启用G1垃圾回收器 | | `-XX:MaxGCPauseMillis` | 200ms | 设置期望的最大停顿时间目标(非硬性保证) | | `-XX:InitiatingHeapOccupancyPercent` | 45% | 触发并发标记周期的堆占用率阈值 | | `-XX:G1HeapRegionSize` | 根据堆大小计算 | 设置Region大小(1MB~32MB,2的幂) | | `-XX:G1NewSizePercent` | 5% | 年轻代占堆的最小比例 | | `-XX:G1MaxNewSizePercent` | 60% | 年轻代占堆的最大比例 | | `-XX:ConcGCThreads` | 根据CPU计算 | 并发标记阶段使用的线程数 | | `-XX:ParallelGCThreads` | 根据CPU计算 | 并行回收阶段的线程数(如Young GC) | | `-XX:G1ReservePercent` | 10% | 堆内存保留比例,用于晋升失败时的备用空间 | | `-XX:G1HeapWastePercent` | 5% | 允许的堆浪费百分比,达到该值会触发混合回收 | #### 调优建议: 1. **设置停顿时间目标**:根据应用需求调整`-XX:MaxGCPauseMillis`(如50ms),但设置过小可能导致频繁GC。 2. **避免Full GC**: - 增加`-XX:InitiatingHeapOccupancyPercent`(如60%),避免过早触发混合回收。 - 增大`-XX:G1ReservePercent`(如15%),预留更多空间应对晋升失败。 3. **调整Region大小**:大对象较多时,可增大`-XX:G1HeapRegionSize`减少Humongous对象。 4. **并发线程数**:高并发场景可增加`-XX:ConcGCThreads`加速标记过程。 ### 三、适用场景 - 堆内存较大(>6GB)且要求低延迟的应用。 - 需要平衡吞吐量和停顿时间的场景。 - 替代CMS,避免老年代碎片问题。 > 通过合理调优,G1可在满足低延迟的同时保持较高吞吐量[^1][^3]。 --- ### 相关问题 1. **G1与ZGC/Shenandoah在延迟控制上有何差异?** 2. **如何诊断G1的Full GC问题?** 3. **G1的RSet如何维护?对性能有何影响?** 4. **G1的混合回收阶段如何选择回收的Region?** 5. **G1的SATB算法如何解决漏标问题?**</think>### G1垃圾回收器工作原理 G1(Garbage-First)是JDK 7u4引入的面向服务端应用的垃圾回收器,其核心设计目标是在**可控的停顿时间**内实现**高吞吐量**,特别适合大内存(>6GB)和多核CPU环境[^1][^3]。以下是其工作原理的核心机制: --- #### 1. **分区化内存布局** - **Region结构**:将堆划分为多个大小相等的区域(Region,默认2,048个),每个Region可以是Eden、Survivor、Old或Humongous(存放大对象)区。 - **动态角色分配**:Region类型在GC过程中动态变化,避免传统分代模型的固定划分。 - **优势**:允许更灵活的内存管理,减少内存碎片。 #### 2. **回收过程分阶段** | **阶段** | **工作内容** | **是否STW** | **耗时占比** | |-------------------|---------------------------------------------|-------------|--------------| | **年轻代GC** | 回收Eden+Survivor区(复制算法) | STW | 短(毫秒级) | | **并发标记** | 扫描堆中存活对象(SATB算法) | 并发 | 长 | | **混合回收** | 回收年轻代+高收益老年代Region(复制算法) | STW | 可控 | | **Full GC** | 仅当回收速度跟不上分配速度时触发(应避免) | STW | 长 | #### 3. **核心算法机制** - **RSet(记忆集)** 每个Region维护一个RSet,记录其他Region对本Region的引用。GC时只需扫描RSet而非全堆,减少扫描范围。 ```java // 伪代码:RSet记录跨Region引用 class Region { HashTable<Region*, CardTable*> rset; // 记录引用来源 } ``` - **SATB(Snapshot-At-The-Beginning)** 并发标记开始时对堆做快照,确保标记期间新分配对象不被遗漏,解决“漏标”问题[^1]。 - **停顿预测模型** 基于历史GC数据预测本次回收时间,动态选择回收Region数量以满足`-XX:MaxGCPauseMillis`目标。 #### 4. **回收策略(Garbage-First来源)** 1. 计算每个Region的**回收价值**(垃圾比例 × 回收速度) 2. 优先回收垃圾比例最高的Region(即Garbage-First) 3. 在停顿时间内回收尽可能多的内存 --- ### 关键调优参数 #### 基础参数 | **参数** | **默认值** | **说明** | |-----------------------------------|------------|--------------------------------------------------------------------------| | `-XX:+UseG1GC` | - | 启用G1回收器(必需参数) | | `-XX:MaxGCPauseMillis` | 200ms | **核心目标**:期望最大停顿时间(非硬性保证)[^1] | | `-XX:InitiatingHeapOccupancyPercent` | 45% | 触发并发标记的老年代占用阈值(建议监控调整) | #### 内存与线程控制 | **参数** | **默认值** | **调优建议** | |------------------------------|------------------|---------------------------------------------| | `-XX:G1HeapRegionSize` | 根据堆大小计算 | 大堆(>32GB)建议设16-32MB | | `-XX:G1NewSizePercent` | 5% | 年轻代最小占比,根据对象分配速率调整 | | `-XX:G1MaxNewSizePercent` | 60% | 年轻代最大占比 | | `-XX:ConcGCThreads` | ≈1/4 CPU核心数 | 并发标记线程数(CPU密集时增加) | | `-XX:ParallelGCThreads` | =CPU核心数 | 并行回收线程数(STW阶段使用)[^2] | #### 高级调优 | **参数** | **场景** | |-----------------------------------|--------------------------------------------------------------------------| | `-XX:G1ReservePercent=15` | 防止晋升失败(OOM)的保留内存(默认10%,大堆可增至15-20%) | | `-XX:G1HeapWastePercent=5` | 触发混合回收的堆垃圾比例阈值(默认5%,降低可提前回收) | | `-XX:G1MixedGCCountTarget=8` | 混合回收阶段的最大回收次数(增加可降低单次停顿时间) | --- ### 调优实践建议 1. **目标停顿时间** ```bash -XX:MaxGCPauseMillis=100 # 典型值100-200ms ``` 设置过高可能导致Full GC;过低会过度收缩年轻代,引发频繁GC。 2. **避免Full GC** - 增加`G1ReservePercent`预留内存 - 降低`InitiatingHeapOccupancyPercent`(如40%)提前触发并发标记 - 监控`GC Pause`和`Allocation Rate`(工具:GC日志+Prometheus) 3. **大对象优化** ```bash -XX:G1HeapRegionSize=16m # 若Humongous对象过多 -XX:G1MixedGCLiveThresholdPercent=85 # 跳过存活率高的老年代Region ``` > 通过合理调优,G1可做到99.9%停顿<200ms,吞吐量>90%[^3]。 --- ### 与其他回收器对比 | **场景** | **推荐回收器** | **原因** | |------------------|----------------------|------------------------------------------| | 客户端/小堆 | Serial GC | 低开销 | | Web服务(JDK8+) | **G1**(默认) | 平衡停顿与吞吐[^3] | | 金融/实时系统 | ZGC | 亚毫秒级停顿(JDK15+) | | 大数据计算 | Parallel GC | 最大化吞吐量[^3] | --- ### 相关问题 1. **G1的SATB算法如何解决并发标记期间的漏标问题?** 2. **如何通过GC日志诊断G1的Full GC原因?** 3. **G1与ZGC在内存布局和回收策略上有何本质区别?** 4. **为什么G1适合大堆而CMS不适合?** 5. **如何监控G1的RSet对性能的影响?**
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值