java虚拟机-G1 回收器笔记

既然我们已经有了前面几个强大的 GC ,为什么还要发布 Garbage First ( G1 ) GC ?

原因就在于应用程序所应对的业务越来越庞大、复杂,用户越来越多,没有 GC 就不能保证应用程序正常进行,而经常造成 STW 的 GC 又跟不上实际的需求,所以才会不断地尝试对 GC 进行优化。 G1 ( Garbage-First )垃圾回收器是在 Java 7 update 4 之后引入的一个新的垃圾回收器,是当今收集器技术发展的最前沿成果之一

与此同时,为了适应现在不断扩大的内存和不断增加的处理器数量,进一步降低暂停时间( pause time ),同时兼顾良好的吞吐量。

官方给 G1 设定的目标是在延退可控的情况下获得尽可能高的吞吐量,所以才担当起“全功能收集器”的重任与期望

为什么名字叫做 Garbage-First ( G1 )呢?
因为G 1 是一个并行回收器,它把堆内存分割为很多不相关的区域( Region )(物理上不连续的)。使用不同的 Region 来表示 Eden 、幸存者 0 区,幸存者 1 区,老年代等

G1 GC 有计划地避免在整个 Java 堆中进行全区域的垃圾收集。G1 跟踪各个 Region 里面的垃圾堆积的价值大小(回收所获得的空间大小以及回收所需时间的经验值),在后台维护一个优先列表,每次根据允许的收集时间,优先回收价值最大的 Region 。

由于这种方式的侧重点在于回收垃圾最大量的区间( Region ),所以我们给 G1 一个名字:垃圾优先( Garbage First )。

G1 ( Garbage-First )是一款面向服务端应用的垃圾收集器,主要针对配备多核 CPU 及大容量内存的机器,以极高概率满足 GC 停顿时间的同时,还兼具高吞吐量的性能特征

在 JDK 1.7 版本正式启用,移除了 Experimental 的标识,是 JDK 9 以后的默认垃圾回收器,取代了 CMS 回收器以及 Parallel + Parallel Old 组合。被 Oracle 官方称为“全功能的垃圾收集器”。

与此同时, CMS 已经在 JDK 9 中被标记为废弃( deprecated )。在 JDK 8 中还不是默认的垃圾回收器,需要使用 -XX:+UseG1GC 来启用。

G1 回收器的特点(优势)

与其他 GC 收集器相比, G1 使用了全新的分区算法,其特点如下所示

并行与并发

并行性: G1 在回收期间,可以有多个 GC 线程同时工作,有效利用多核计算能力。此时用户线程 STW
并发性: G1 拥有与应用程序交替执行的能力,部分工作可以和应用程序同时执行,因此,一般来说,不会在整个回收阶段发生完全阻塞应用程序的情况
分代收集

从分代上看, G1 依然属于分代型垃圾回收器,它会区分年轻代和老年代,年轻代依然有 Eden 区和 Survivor 区。但从堆的结构上看,它不要求整个 Eden 区、年轻代或者老年代都是连续的,也不再坚持固定大小和固定数量。
将堆空间分为若干个区域( Region ),这些区域中包含了逻辑上的年轻代和老年代。
和之前的各类回收器不同,它同时兼顾年轻代和老年代。对比其他回收器,或者工作在年轻代,或者工作在老年代;
空间整合

CMS :“标记-清除” 算法、内存碎片、若干次 GC 后进行一次碎片整理
G1 将内存划分为一个个的 region 。内存的回收是以 region 作为基本单位的。 Region 之间是复制算法,但整体上实际可看作是标记-压缩( Mark - Compact )算法,两种算法都可以避免内存碎片。这种特性有利于程序长时间运行,分配大对象时不会因为无法找到连续内存空间而提前触发下一次 GC 。尤其是当 Java 堆非常大的时候, G1 的优势更加明显。
可预测的停顿时间模型(即:软实时 soft real - time )

这是 G1 相对于 CMS 的另一大优势, G1 除了追求低停顿外,还能建立可预测的停顿时间模型,能让使用者明确指定在一个长度为 M 毫秒的时间片段内,消耗在垃圾收集上的时间不得超过 N 毫秒
由于分区的原因, G1 可以只选取部分区域进行内存回收,这样缩小了回收的范围,因此对于全局停顿情况的发生也能得到较好的控制。
G1 跟踪各个 Region 里面的垃圾堆积的价值大小(回收所获得的空间大小以及回收所需时间的经验值),在后台维护一个优先列表,每次根据允许的收集时间,优先回收价值最大的 Region 。保证了 G1 收集器在有限的时间内可以获取尽可能高的收集效率。
相比于 CMS GC , G1 未必能做到 CMS 在最好情况下的延时停顿,但是最差情况要好很多。
G1 回收器的缺点
相较于 CMS , G1 还不具备全方位、压倒性优势。比如在用户程序运行过程中,G1 无论是为了垃圾收集产生的内存占用( Footprint )还是程序运行时的额外执行负载( Overload )都要比 CMS 要高。

从经验上来说,在小内存应用上 CMS 的表现大概率会优于 G1 ,而 G1 在大内存应用上则发挥其优势。平衡点在 6 - 8 GB 之间。

G1 回收器的参数设置

XX:+UseG1GC 手动指定使用 G1 收集器执行内存回收任务
-XX:G1HeapRegionSize 设置每个 Region 的大小。值是 2 的幂,范围是 1 MB 到 32 MB 之间,目标是根据最小的 Java 堆大小划分出约 2048 个区域。默认是堆内存的 1/2000 。
-XX:MaxGCPausemillis 设置期望达到的最大 GC 停顿时间指标( JVM 会尽力实现,但不保证达到)。默认值是 200 ms
-XX:ParallelGCThread 设置 STW 时 GC 线程数的值。最多设置为 8
-XX:ConcGCThreads 设置并发标记的线程数。将 n 设置为并行垃圾回收线程数( ParallelGCThread )的 1/4 左右。
-XX:InitiatingHeapOccupancyPercent 设置触发并发 GC 周期的 Java 堆占用率阈值。超过此值,就触发 GC 。默认值是 45 。
G1 回收器的常见操作步骤
G1 的设计原则就是简化 JVM 性能调优,开发人员只需要简单的三步即可完成调优

开启 G1 垃圾收集器
设置堆的最大内存
设置最大的停顿时间
G1 中提供了三种垃圾回收模式: Young GC 、 Mixed GC 和 Full GC ,在不同的条件下被触发。

G1 回收器的适用场景

面向服务端应用,针对具有大内存、多处理器的机器。(在普通大小的堆里表现并不惊喜)最主要的应用是需要低 GC 延迟,并具有大堆的应用程序提供解决方案如:在堆大小约 6 GB 或更大时,可预测的暂停时间可以低于 0.5 秒:( G1 通过每次只清理一部分而不是全部的 Region 的增量式清理来保证每次 GC 停顿时间不会过长)。用来替换掉 JDK 1.5 中的 CMS 收集器;在下面的情況时,使用 G1 可能比 CMS 好超过 56% 的 Java 堆被活动数据占用;对象分配频率或年代提升频率变化很大GC 停顿时间过长(长于 0.5 至 1 秒)。
HotSpot 拉圾收集器里,除了 G1 以外,其他的垃圾收集器使用内置的 JVM 线程执行 GC 的多线程操作,而 G1 可以采用应用线程承担后台运行的 GC 工作,即当 JVM 的 GC 线程处理速度慢时,系统会调用应用程序线程帮助加速垃圾回收过程。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值