G1回收器

目录

前言

一、G1的适用场景和特点

1:适用场景

2:特点

二:理解G1的运行过程

1:G1的Heap划分

2:G1收集器运行:标记,回收.

三:G1相关参数

四:日志分析

五:优化建议



前言

G1 GC(垃圾优先型垃圾回收器)适用于Java HotSpotVM 的低停顿、面向服务器的高可用分代式垃圾回收器。
G1 GC使用并发和并行阶段实现其目标暂停时间,并保持良好的吞吐量。G1jdk7u04中作为正式版发布,jdk6U14中作为测试版发布,
jdk6
使用G1需要使用-XX:+UnlockExperimentalVMOptions 参数打开,jdk6的很多G1调整参数被调整不建议使用。


一、G1的适用场景和特点

1:适用场景

1)适用在big heap(6GB or larger)场景,不能容忍长时间停顿(Full GC)的服务器场景.
2)
有大量存活对象(超过50%)的场景.例如:数据服务器场景.HbaseCassandra.
3)
解决传统的parNew+CMS垃圾收集算法中,有很多晋代失败(promotion failed)/并发失败(concurrent mode failure),然后做Full gc..

2:特点

1)G1可以控制最长停顿时间(-XX:MaxGCPauseMillis),这是个预计值,G1会根据这个时间制定回收策略,但是设置过低停顿回造成低吞吐。
2)G1基于复制的算法,回收过程不会产生碎片,这是相比CMS最大的优势.
3)G1
heap分割成很多大小相等的区域(region),不再使用固定空间分代的方式,采用逻辑分代:Eden,Survivor,Old。每个逻辑分代含有若干区域且数量可以动态调整.
通过使用jmap -heap 得到的堆统计信息可以更好的理解逻辑分代:

Heap Configuration:
   MinHeapFreeRatio = 40
   MaxHeapFreeRatio = 70
   MaxHeapSize      = 25769803776 (24576.0MB)
   NewSize          = 1363144 (1.2999954223632812MB)
   MaxNewSize       = 17592186044415 MB
   OldSize          = 5452592 (5.1999969482421875MB)
   NewRatio         = 2
   SurvivorRatio    = 6
   PermSize         = 100663296 (96.0MB)
   MaxPermSize      = 100663296 (96.0MB)
   G1HeapRegionSize = 8388608 (8.0MB)
G1 Heap:
   regions  = 3072
   capacity = 25769803776 (24576.0MB)
   used     = 11232244096 (10711.902709960938MB)
   free     = 14537559680 (13864.097290039062MB)
   43.58684370915095% used
G1 Young Generation:
Eden Space:
   regions  = 29
   capacity = 1233125376 (1176.0MB)
   used     = 243269632 (232.0MB)
   free     = 989855744 (944.0MB)
   19.727891156462587% used
Survivor Space:
   regions  = 14
   capacity = 117440512 (112.0MB)
   used     = 117440512 (112.0MB)
   free     = 0 (0.0MB)
   100.0% used
G1 Old Generation:
   regions  = 1298
   capacity = 24419237888 (23288.0MB)
   used     = 10871533952 (10367.902709960938MB)
   free     = 13547703936 (12920.097290039062MB)
   44.52036546702567% used

二:理解G1的运行过程

1:G1Heap划分

G1 GC 启动后把堆被划分成大小相同的多个区域(Region)
区域的大小由(-XX:G1HeapRegionSize)指定,不指定区域大小会从1MB32MB自动制定,区域大小确定后不会做动态调整.
整个heap划分为Eden,Survivor,Old三个不连续的逻辑区域。
如下图标示G1对整个heap的划分
图一

运行过程中,G1会为每个Region使用Remembered Set来维护对象引用,
应用程序在对Reference类型的数据进行写操作时会产生一个Write Barrier暂时中断写操作,
检查Reference引用的对象是否处于不同的Region之中,如果是,便通过CardTable把相关引用信息记录到被引用对象所属的RegionRemembered Set之中。
当进行内存回收时,在GC根节点的枚举范围中加入Remembered Set来避免对全堆扫描.

2:G1收集器运行:标记,回收.

1)标记:

初始标记阶段:此阶段,G1GC对根进行标记。该阶段与年轻代垃圾(STW)回收密切相关。
根区域扫描阶段:G1GC 在初始标记的存活区扫描对老年代的引用,并标记被引用的对象.该阶段与应用程序同时运行,该阶段完成后,才能开始下一次年轻代垃圾回收。
并发标记阶段:G1GC 在整个堆中查找存活对象。该阶段与应用程序同时运行,可以被年轻代垃圾回收中断。
重新标记阶段:该阶段是 STW 回收,帮助完成标记周期。G1 GC 清空 SATB 缓冲区,跟踪未被访问的存活对象,并执行引用处理。
清理阶段:在这个最后阶段,G1 GC 执行统计和 RSet 清理的STW操作。在统计期间,G1GC 会识别完全空闲的区域和可供进行混合垃圾回收的区域。
清理阶段会将空白区域重置并返回到空闲列表。

2)回收:

回收过程按回收区域集合(CollectionSets/CSets)划分.CSets可以包含(Eden,survivor/old)中的region,CSets占用内存一般小于整个jvm1%;

年轻代垃圾回收:

G1 Young GC同时回收eden区域和上次垃圾回收的存活区域。Eden survivor的存活对象被疏散(复制/移动)到新的区域集。
被疏散对象的目标区域取决于对象的年龄,达到晋升年龄的对象疏散到老年代区域,
否则疏散到存活区,并将它包含在下一次年轻代或混合垃圾回收的CSet中。

混合垃圾回收:

G1 Mixd GC同时回收Eden,survivor,old的存活区域。当成功完成并发标记周期后,G1 GC从执行年轻代垃圾回收切换为执行混合垃圾回收。
在混合垃圾回收期间,G1GC 将一些旧的区域添加到 eden 和存活区供将来回收。G1GC 回收了足够的旧区域后(经过多次混合垃圾回收),
G1将恢复执行年轻代垃圾回收,直到下一次标记周期完成。

G1GC不同阶段暂定和描述总结

如下表:

Phase

Description

(1) Initial Mark
(Stop the World Event)

This is a stop the world event. With G1, it is piggybacked on a normal young GC. Mark survivor regions (root regions) which may have references to objects in old generation.

(2) Root Region Scanning

Scan survivor regions for references into the old generation. This happens while the application continues to run. The phase must be completed before a young GC can occur.

(3) Concurrent Marking

Find live objects over the entire heap. This happens while the application is running. This phase can be interrupted by young generation garbage collections.

(4) Remark
(Stop the World Event)

Completes the marking of live object in the heap. Uses an algorithm called snapshot-at-the-beginning (SATB) which is much faster than what was used in the CMS collector.

(5) Cleanup
(Stop the World Event and Concurrent)

  • Performs accounting on live objects and completely free regions. (Stop the world)
  • Scrubs the Remembered Sets. (Stop the world)
  • Reset the empty regions and return them to the free list. (Concurrent)

(*) Copying
(Stop the World Event)

These are the stop the world pauses to evacuate or copy live objects to new unused regions. This can be done with young generation regions which are logged as [GC pause (young)]. Or both young and old generation regions which are logged as [GC Pause (mixed)].

三:G1相关参数

-XX:G1HeapRegionSize=n
设置的 G1 区域的大小。值是 2 的幂,范围是 1 MB 32 MB 之间。目标是根据最小的 Java 堆大小划分出约 2048 个区域。

-XX:MaxGCPauseMillis=200
为所需的最长暂停时间设置目标值。默认值是 200 毫秒。指定的值不适用于您的堆大小。

-XX:ParallelGCThreads=cpus
设置年轻代垃圾回收(STW)工作线程数的值。将 n 的值设置为逻辑处理器的数量。n 的值与逻辑处理器的数量相同,G1根据cpu数量设置不同的初始值。

-XX:ConcGCThreads=cpus/4
设置并发标记的线程数。将n设置为并行垃圾回收线程数 (ParallelGCThreads) 1/4 左右。

-XX:InitiatingHeapOccupancyPercent=45
设置触发标记周期的Java堆占用率阈值。默认占用率是整个 Java 堆的 45%

-XX:G1HeapWastePercent=10
设置G1愿意浪费的堆百分比。如果可回收百分比小于堆废物百分比。默认值是 10%

-XX:G1MixedGCCountTarget=8
设置标记周期完成后,对旧区域执行混合垃圾回收的目标次数。默认值是 8 次混合垃圾回收。
混合回收的目标是控制在此目标次数以内。

-XX:G1ReservePercent=10
设置作为空闲空间的预留内存百分比,以降低目标空间溢出的风险。默认值是 10%。增加或减少百分比时,需要评估Java堆的量。

四:日志分析

Poonam Bajaj 大神写了G1的日志格式分析 , 直接引用她的Understanding_G1_GC_LOGS

五:优化建议

1:不要使用-Xmn/-XX:NewRatio等设置年轻代大小,G1使用逻辑分代,年轻代大小是动态调整的.且固定年轻代的大小会覆盖暂停时间目标


2:暂停时间目标(-XX:MaxGCPauseMillis):设置所需的软实时目标,G1GC 会尽量满足.当对垃圾回收进行评估或调优时,都会涉及到延迟与吞吐量的取舍。需要G1高吞吐量时,暂停时间目标不要太严苛。


3:调优混合垃圾回收时,需合理调整以下参数:
-XX:InitiatingHeapOccupancyPercent
用于更改标记阈值。更小的值意味着更快的触发标记周期。
-XX:G1MixedGCCountTarget 用于调整Old区域的CSet集合。


4:G1溢出/耗尽引发的FullGc
2014-03-06T10:01:28.216+0800: 67998.279: [GC pause (mixed) (to-space exhausted), 13.8681600 secs]
2014-03-04T10:01:42.086+0800: 68012.149: [GC pause (mixed) (to-space overflow), 3.0012670 secs]

优化参数:
增加-XX:G1ReservePercent 选项的值(并相应增加总的堆大小,"目标空间"预留更多内存空间。
减少 -XX:InitiatingHeapOccupancyPercent 提前启动标记周期。
增加 -XX:ConcGCThreads 选项的值来增加并行标记线程的数目,加快标记速度。


5:避免巨型对象
G1对于任何超过区域一半大小的对象都被视为巨型对象”,巨型区域直接被分配到老年代中.
巨型区域是一个连续的区域集。StartsHumongous 标记该连续集的开始,ContinuesHumongous 标记它的延续.
所以没有使用的巨型对象的终点与上个区域的终点之间的空间无法被使用,
如果对象只是略大于堆区域大小的倍数,未使用的空间可能会导致堆碎片化。
巨型对象也可能分配导致连续的并发周期,并且此类分配导致老年代碎片化
通过增加-XX:G1HeapRegionSize的值,提高巨型对象的门槛(G1HeapRegionSize/2)

### G1垃圾回收器工作原理 G1(Garbage First)是一种服务器端的垃圾回收器,专为多处理器、大容量内存环境设计。其核心目标是在提供高性能的同时保持低延迟。以下是关于G1垃圾回收器的关键特性及其配置方法: #### 1. **堆内存分区** G1将整个堆划分为多个大小相等的区域(Region),这些区域可以属于不同的逻辑部分,如新生代(Young Generation)、老年代(Old Generation)以及巨对象区(Humongous Region)。这种灵活的设计使得G1能够更高效地管理不同类型的对象。 - 新生代通常由Eden区和两个Survivor区组成。 - 老年代用于存储生命周期较长的对象。 - Humongous区专门用于存储无法放入常规区域的大对象[^2]。 #### 2. **暂停预测模型** G1通过一种称为“暂停预测模型”的机制来控制停顿时间。它允许用户指定期望的最大停顿时间(`MaxGCPauseMillis` 参数),并尝试在此范围内完成垃圾回收操作。具体来说,G1会选择一组适合当前条件的区域进行回收,从而减少全局停顿的时间。 #### 3. **并发标记阶段** 在G1中,大部分标记过程都是与应用程序线程并发运行的。这减少了因完全停止程序而导致的整体停顿时间。主要步骤包括: - 初始标记:短暂暂停以记录根节点集合的信息。 - 并发标记:遍历对象图并与应用线程同时执行。 - 最终标记:再次短暂停留以处理任何剩余的任务。 #### 4. **混合收集** 除了清理年轻代外,G1还可以在同一轮次中选择一些老年代区域一起参与回收。这种方法被称为“混合模式”,有助于逐步降低整体的老年区内存压力而无需触发完整的GC事件。 #### 配置建议 基于实际案例中的经验教训,合理设置JVM参数至关重要。例如,在某项目中调整新生代与老年间的比例至2:1后显著改善了性能表现——不仅消除了频繁发生的Full GC现象,还将YGC次数大幅削减下来[^3]。 ```bash java -XX:+UseG1GC \ -Xms8g -Xmx8g \ -XX:NewRatio=2 \ -XX:InitiatingHeapOccupancyPercent=45 \ -XX:MaxGCPauseMillis=200 \ -jar your-application.jar ``` 上述命令片段展示了如何启用G1GC,并设置了初始/最大堆大小均为8GB;定义了当堆占用率达到约45%时开始周期性的Minor GC活动;最后设定了预期最长GC暂停时间为200毫秒。 ### 工具支持 对于监控和诊断目的而言,像VisualVM这样的工具非常有用。它可以直观展示系统的资源消耗状况,帮助开发者快速定位潜在瓶颈所在位置[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值