美文网首页Java
G1垃圾收集器入门

G1垃圾收集器入门

作者: VIPSHOP_FCS | 来源:发表于2017-09-28 15:36 被阅读1915次

    1. 前言

    9月21日,跳票多次的Java 9终于在这一天发布了,数百万程序猿/媛们普大喜奔,内流满面,纷纷表示很愿意在下一个项目中使用Java 8了。本次Java 9发布带来了91个重要的功能,其中跟GC相关的就有4个,说明GC在Java世界中仍然是一个重要的组成部分,4个更新具体如下:

    -  JEP 214:  删除在JDK8中不推荐使用的GC组合

    -  JEP 248:  将 G1收集器设置为默认垃圾收集器

    -  JEP 291: 将CMS垃圾收集器置为不推荐 CMS (在JAVA7/8时代作为是高并发应用首选垃圾收集器,在新版本中置为不推荐表示不理解)

    - JEP 271: 使用JEP158引入统一JVM日志框架GC日志

    以上4个功能中,最引入注目的莫过于将G1设置默认垃圾回收器。为什么要将G1设为默认垃圾回收器呢?

    从JDK官方的说明中可以看到,G1是一个低延迟垃圾回收器,对于应用的整体用户体验来讲,低延迟的收集器要好于高吞吐的收集器,故将G1置为默认收集器,在Java 7/8中的默认收集器是面对高吞吐的Parallel GC。

    低延尽代表着响应能力,在架构设计要求中常常可以看到响应能力和吞吐量两个指标经常是成对出现。一般来讲,我们对Java应用进行优化主要也是针对这两个指标。

    响应能力是指应用或者系统在多快能够返回请求的数据,比如说点击一个按钮多快有反应,多快能够打开一个网页或者多快能够返回一次数据库查询等。对于面对响应能力的应用来说,长时间的停顿是不可接受的。

    吞吐量专注于在某个时间段内能够处理最大工作负载,比如说每分钟处理多个少事务,每分钟完成了多少个任务或者每分钟完成了多少个数据库查询。对于面对吞吐量的应用来讲,较长的停顿时间是能够接受的,高吞吐量应用关注的是系统处理能力,单个事务,任务或者查询的响应速度不是它的考虑。

    2. G1 介绍

    G1 收集器是一个面向服务器模式的垃圾收集器,主要为多CPU机器和大内存机器设计。它可以尽可能在达到高吞吐量同时满足垃圾收集暂停时间目标。G1 有以下几个优点:

    1. 能够像CMS收集器一样跟应用线程并行操作

    2. 收缩空闲空间不会造成由长GC引起的应用停顿时间。

    3. 更精确的预测GC停顿时间

    4. 不会牺牲太多的吞吐效率

    5. 不请求较多的Java堆

    传统的垃圾收集器像Serial, Parallel, CMS 全部都将Java堆分成三个固定内存大小的部分,如年轻代,年老代和永久代,所有的内存中的Java对象都在三个部分中结束。

    G1 收集器采用了不同的方法,它将整个Java堆分成2000个左右相同大小的堆区域,这些区域集像以前的收集器一样被分配到不同的角色,如Eden, Survivor和Old, 但是没有固定的区域数量被明确固定在某个角色上,这将为内存使用上提供了更大的灵活性。

    在执行垃圾收集时,G1操作十分类似于CMS收集器。G1执行一个并发全局标记阶段贯穿整个Java堆去判断对象的活跃度,标记阶段结束后,收集器知道哪一些区域是空的或者接近空的,它将先收集这些空的区域,通常会释放大量的内存空间,G1将其收集和压缩活动集中在可能充满可回收对象的堆区域上, 这也是收集器命名为G1的原因。G1使用了一个停顿预测模型根去满足用户自定义的停顿时间目标并且根据该目标选择一定数量的区域进行回收。

    G1通过转移的方法将已被G1标识为区域当作可回收的垃圾进行回收,它把对象从1个或者多个区域中复制到单个区域,在复制的同时进行压缩对象和释放内存,所有的转移过程通过多个处理器并行处理以降低暂停时间和增加吞吐量。因此,每一次垃圾回收,G1收集器持续地在用户预定的暂停时间内减少内存碎片。相对而言,CMS收集器不会做压缩,而PARALlelOld 收集器是对整个Java堆执行压缩,那么将导致较长停顿时间。

    另外一个重要的点是G1不是一个实时的收集器,它只是最大程度去满足预定的停顿时间目标,但不是绝对满足。收集器通过之前垃圾回收数据预估一个在预定停顿时间内可回收的区域数量,因此G1是根据一个合理的成本进行收集。

    如果应用从CMS收集器或者ParallelOldGC到G1,你可能会发现相同数据规模情况下G1占用的内存比以前多了一些,多出的一些内存主要是用于存储账单数据结果,如Remembered Sets和Collection Sets.

    - Remembered Sets, RSets跟踪每一个区域的对象引用,每一个区域都有一个Rsets, 它在区域启用一个独立且并行的集合,RSets大约增加5%左右的Overhead。

    - Collection Sets, CSets是放置可被收集器回收的区域集合,所有在这个集合的数据对象在垃圾回收期间均可被转移,这些区域可能是Eden,Survivor 或者老年代。CSets大约有增加1%左右的overhead.

    3. G1 回收步骤

    4. G1 最佳实践

    1. 年轻代大小:避免使用?-Xmn?选项或?-XX:NewRatio?等其他相关选项显式设置年轻代大小,因为固定年轻代的大小会覆盖暂停时间目标。

    2. 暂停时间目标:每当对垃圾回收进行评估或调优时,都会涉及到延迟与吞吐量的权衡。G1是增量垃圾回收器, 其吞吐量目标是 90% 的应用程序时间和 10%的垃圾回收时间。因此,暂停时间目标不要太严苛。目标太过严苛表示您愿意承受更多的垃圾回收开销,而这会直接影响到吞吐量。

    3. 掌握混合垃圾回收:当您调优混合垃圾回收时,请尝试以下选项

     -XX:InitiatingHeapOccupancyPercent

     -XX:G1MixedGCLiveThresholdPercent?和?-XX:G1HeapWastePercent

     -XX:G1MixedGCCountTarget?和?-XX:G1OldCSetRegionThresholdPercent

    5. G1 主要参数配置介绍

    6. 参考资源

    - Getting Started with the G1 Garbage Collector

    - G1: One Garbage Collector To Rule Them All

    - Java7中G1垃圾收集器使用和流程总结

    - 译文-G1收集器

    7. 作者注

    最近所负责的多个系统陆续的由JDK7升级到JDK8并且频发由于长时间GC的停顿导致系统报警, 团队成员逐渐考虑将目前的CMS收集器替换为G1以换取更好的响应能力,遂将此篇作为团队成员理解并了解G1收集器的入门指南。

    相关文章

      网友评论

        本文标题:G1垃圾收集器入门

        本文链接:https://www.haomeiwen.com/subject/vubfextx.html