什么是G1垃圾回收算法

转载自 什么是G1垃圾回收算法

为解决CMS算法产生空间碎片和其它一系列的问题缺陷,HotSpot提供了另外一种垃圾回收策略,G1(Garbage First)算法,通过参数 -XX:+UseG1GC来启用,该算法在JDK 7u4版本被正式推出,官网对此描述如下:

The Garbage-First (G1) collector is a server-style garbage collector, targeted for multi-processor machines with large memories. It meets garbage collection (GC) pause time goals with a high probability, while achieving high throughput. The G1 garbage collector is fully supported in Oracle JDK 7 update 4 and later releases. The G1 collector is designed for applications that:

  • Can operate concurrently with applications threads like the CMS collector.

  • Compact free space without lengthy GC induced pause times.

  • Need more predictable GC pause durations.

  • Do not want to sacrifice a lot of throughput performance.

  • Do not require a much larger Java heap.

G1垃圾收集算法主要应用在多CPU大内存的服务中,在满足高吞吐量的同时,竟可能的满足垃圾回收时的暂停时间,该设计主要针对如下应用场景:

  • 垃圾收集线程和应用线程并发执行,和CMS一样

  • 空闲内存压缩时避免冗长的暂停时间

  • 应用需要更多可预测的GC暂停时间

  • 不希望牺牲太多的吞吐性能

  • 不需要很大的Java堆 (翻译的有点虚,多大才算大?)

堆内存结构

1、以往的垃圾回收算法,如CMS,使用的堆内存结构如下:

  • 新生代:eden space + 2个survivor

  • 老年代:old space

  • 持久代:1.8之前的perm space

  • 元空间:1.8之后的metaspace

这些space必须是地址连续的空间。

2、在G1算法中,采用了另外一种完全不同的方式组织堆内存,堆内存被划分为多个大小相等的内存块(Region),每个Region是逻辑连续的一段内存,结构如下:

每个Region被标记了E、S、O和H,说明每个Region在运行时都充当了一种角色,其中H是以往算法中没有的,它代表Humongous,这表示这些Region存储的是巨型对象(humongous object,H-obj),当新建对象大小超过Region大小一半时,直接在新的一个或多个连续Region中分配,并标记为H。

Region

堆内存中一个Region的大小可以通过 -XX:G1HeapRegionSize参数指定,大小区间只能是1M、2M、4M、8M、16M和32M,总之是2的幂次方,如果G1HeapRegionSize为默认值,则在堆初始化时计算Region的实践大小,具体实现如下:

默认把堆内存按照2048份均分,最后得到一个合理的大小。

GC模式

G1中提供了三种模式垃圾回收模式,young gc、mixed gc 和 full gc,在不同的条件下被触发。

young gc

发生在年轻代的GC算法,一般对象(除了巨型对象)都是在eden region中分配内存,当所有eden region被耗尽无法申请内存时,就会触发一次young gc,这种触发机制和之前的young gc差不多,执行完一次young gc,活跃对象会被拷贝到survivor region或者晋升到old region中,空闲的region会被放入空闲列表中,等待下次被使用。

| 参数 | 含义 | | :-: | --- | | -XX:MaxGCPauseMillis | 设置G1收集过程目标时间,默认值200ms | | -XX:G1NewSizePercent | 新生代最小值,默认值5% | | -XX:G1MaxNewSizePercent | 新生代最大值,默认值60% |

mixed gc

当越来越多的对象晋升到老年代old region时,为了避免堆内存被耗尽,虚拟机会触发一个混合的垃圾收集器,即mixed gc,该算法并不是一个old gc,除了回收整个young region,还会回收一部分的old region,这里需要注意:是一部分老年代,而不是全部老年代,可以选择哪些old region进行收集,从而可以对垃圾回收的耗时时间进行控制。

那么mixed gc什么时候被触发?

先回顾一下cms的触发机制,如果添加了以下参数:

-XX:CMSInitiatingOccupancyFraction=80 
-XX:+UseCMSInitiatingOccupancyOnly

当老年代的使用率达到80%时,就会触发一次cms gc。

相对的,mixed gc中也有一个阈值参数 -XX:InitiatingHeapOccupancyPercent,当老年代大小占整个堆大小百分比达到该阈值时,会触发一次mixed gc.

mixed gc的执行过程有点类似cms,主要分为以下几个步骤:

  1. initial mark: 初始标记过程,整个过程STW,标记了从GC Root可达的对象

  2. concurrent marking: 并发标记过程,整个过程gc collector线程与应用线程可以并行执行,标记出GC Root可达对象衍生出去的存活对象,并收集各个Region的存活对象信息

  3. remark: 最终标记过程,整个过程STW,标记出那些在并发标记过程中遗漏的,或者内部引用发生变化的对象

  4. clean up: 垃圾清除过程,如果发现一个Region中没有存活对象,则把该Region加入到空闲列表中

full gc

如果对象内存分配速度过快,mixed gc来不及回收,导致老年代被填满,就会触发一次full gc,G1的full gc算法就是单线程执行的serial old gc,会导致异常长时间的暂停时间,需要进行不断的调优,尽可能的避免full gc.



<think>好的,我需要回答用户关于分袋垃圾回收算法的定义和原理的问题。首先,用户可能将“分袋”与“分代”混淆了,因为在常见的垃圾回收算法中并没有“分袋”这一术语,而分代垃圾回收算法(Generational Garbage Collection)是一个核心概念。我需要先确认这一点,并假设用户可能指的是分代算法。 接下来,我需要回顾分代垃圾回收的基本定义。分代算法的核心思想是基于对象的存活时间将堆内存划分为不同的代,通常是年轻代(Young Generation)和老年代(Old Generation)。这样划分的依据是“弱分代假说”,即大多数对象很快就不再被使用,而存活下来的对象可能会存活较长时间。 然后,解释分代垃圾回收的原理。年轻代通常包括Eden区、Survivor区(From和To),对象首先在Eden区分配,经历Minor GC后存活的对象会被移动到Survivor区,多次存活后晋升到老年代。老年代的对象较少被回收,使用Major GC或Full GC。需要提到不同代的垃圾回收频率和算法,比如年轻代常用标记-复制算法,而老年代可能用标记-清除或标记-整理算法。 同时,需要结合用户提供的引用内容,尤其是引用[4]和[5],其中提到了分代收集和G1回收器的分区算法。引用[3]提到不同算法对吞吐量和延迟的影响,这可能与不同代的回收策略有关。例如,Parallel Scavenge使用标记-整理,CMS使用标记-清除,这与分代中的不同处理相关。 要注意用户可能存在的术语混淆,需要明确指出正确的术语,并给出清晰的解释。同时,生成的相关问题需要围绕分代算法的细节、优化和应用,确保问题与主题紧密相关,并帮助用户深入理解。</think>### 分代垃圾回收算法 #### 定义 分代垃圾回收算法(Generational Garbage Collection)是一种基于**对象存活时间差异**的垃圾回收策略,其核心思想是将堆内存划分为不同“代”(Generation),并为每代设计差异化的回收策略[^4]。通常分为**年轻代(Young Generation)**和**老年代(Old Generation)**,少数实现还会包含**永久代/元空间(Perm/Metaspace)**。 #### 原理 1. **分代假说基础** - **弱分代假说**:绝大多数对象生命周期极短,例如临时变量[^4]。 - **强分代假说**:存活时间越长的对象,未来被回收的概率越低。 2. **内存划分与回收策略** - **年轻代** - 包含$Eden$区、$Survivor$区($From$和$To$) - 新对象在$Eden$区分配,触发$Minor GC$时存活对象复制到$Survivor$区 - 对象在多次$Minor GC$中存活后晋升到老年代 - 使用**标记-复制算法**(高吞吐、低延迟)[^3] - **老年代** - 存放长期存活对象 - 触发$Major GC$或$Full GC$时回收 - 使用**标记-清除**(CMS)或**标记-整理**(G1算法[^3][^5] 3. **跨代引用处理** - 通过**记忆集(Remembered Set)**记录跨代引用,避免全堆扫描[^5]。 4. **算法优势** $$回收频率_{\text{年轻代}} \gg 回收频率_{\text{老年代}}$$ 聚焦高频回收短期对象,减少全局停顿时间[^4]。 --- ### 相关问题 1. 年轻代为什么要分为Eden和Survivor区? 2. G1回收器如何改进传统分代算法?[^5] 3. 分代算法中对象年龄阈值如何确定? 4. 记忆集的具体实现原理是什么? 5. 为什么老年代垃圾回收耗时更长?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值