Garbage First(G1)垃圾收集器

引言:G1垃圾收集器采用一个略微不同的手段来解决并行、串行以及CMS GC的众多缺陷。对于大的Java堆来说,通过将Java堆拆分成一个个分区,G1会比其他垃圾收集器有更好的综合表现。
本文选自《Java性能调优指南》。

  G1垃圾收集器采用一个略微不同的手段来解决并行、串行以及CMS GC的众多缺陷。G1将堆拆成一系列的分区,这样在一个时间段内,大部分的垃圾收集操作就只是在一个分区内执行,而不是整个堆或整个(老年)代。

  在G1里,年轻代就是一系列的内存分区,这意味着不用再要求年轻代是一个连续的内存块。类似地,老年代同样也是由一系列的分区组成。这样也就不需要在JVM运行时考虑哪些分区是老年代,哪些是年轻代。事实上,G1通常的运行状态是映射G1分区的虚拟内存随着时间的推移在不同的代之间前后切换。一个G1分区最初被指定为年轻代,经过一次年轻代的回收之后,整个年轻代分区都被划入到未被使用的分区中,那它也就可以被使用在别的地方了。

  一个可用分区能被用于或指定为年轻代或老年代分区。很可能在完成一个年轻代收集之后,一个年轻代的分区在未来的某个时刻被用于老年代分区。同样地,在一个老年代分区完成收集之后,它就成为了可用分区,在未来某个时候作为一个年轻代分区来使用。

  G1年轻代的收集方式是并行stop-the-world。在垃圾收集线程执行过程中,并行stop-the-world回收将暂停所有Java应用线程,而垃圾回收的工作也将通过多个线程来分担。与其他HotSpot垃圾收集器一样,一旦发生一次年轻代垃圾收集,整个年轻代都会被回收。

  而G1老年代的垃圾收集方式与其他HotSpot垃圾收集器有着极大的不同。G1老年代的收集不会为了释放老年代的空间就要求对整个老年代做回收。相反,在任一时刻只有一部分老年代分区会被回收,并且,这部分老年代分区将与一次年轻代收集一起被收集。

贴士
术语混合(mixed)垃圾收集就是用来描述这种一部分老年代分区与年轻代收集结合在一起进行的收集。因此,混合GC就是在一次垃圾收集事件中,所有年轻代分区以及一部分老年代分区将会被回收。换句话说,混合GC就是将要被回收的年轻代与年老代分区的组合。

  与CMS GC类似,当遇到一些极端情况时,诸如老年代空间被消耗完了,会有一个安全措施来收集和压缩整个老年代。

  撇开安全模式下的收集不谈,一个G1老年代收集是由一系列阶段组成,某些是并行stop-the-world的,某些是并行并发的。也就是说,某些阶段是多线程的同时会暂停所有应用线程,而其他阶段是多线程的,但可以与应用线程同时运行。

  当超过Java堆的占用阈值,G1就会启动一次老年代收集。要注意到有一点非常重要,那就是G1中的堆占用阈值,这是根据老年代占用空间与整个Java堆空间相比较得出的。熟悉CMS GC的读者会记得,CMS触发老年代收集所用的占用阈值只是相对于老年代空间本身而言的。在G1中,一旦达到或超过内存堆的占用阈值,一次并发stop-the-world方式的初始标记阶段就会被安排执行。

  初始标记阶段会跟着下一次年轻代收集同时进行。一旦初始标记阶段结束,就会触发一个并发多线程的标记阶段,标记老年代中所有的存活对象。当并发标记阶段结束,并行stop-the-world的重新标记阶段就被启动,标记那些因为在标记阶段同时执行的应用线程导致产生错过的对象。到重新标记阶段结束,G1就拥有了老年代分区的完整信息。如果碰巧老年代分区里一个存活对象都没有,那么在下一个阶段——清除阶段,不用做额外的垃圾收集工作就可以被回收再利用。

  同样也是在重新标记阶段结束,G1能识别出最适合回收的老年代分区集合。

贴士 
在垃圾收集过程中收集的分区集合可以称为收集集合(CSet)。

  选择哪些分区被包含在一个CSet里,是基于有多少空间可以被释放以及G1暂停时间目标。在完成CSet识别之后,G1就在接下来的几次年轻代垃圾收集过程中对CSet中的分区进行回收。也就是说,在接下来的几个年轻代垃圾收集中,除了年轻代分区,还有一部分的老年代分区也将被回收。这就是前面提到的垃圾收集事件中的混合GC类型。

  不管是年轻代还是老年代,G1会把每个收集过垃圾的分区中的存活对象转移到一个可用分区中。一旦存活对象被转移掉,那这个年轻代分区(可能还有老年代分区)就会被回收为可用分区。

  将各老年代分区中的存活对象转移到可用分区会带来一个很有吸引力的结果——在虚拟地址空间里每个转移对象都是前后相连的,对象和对象之间没有碎片化的空余空间。我们回忆一下,CMS、并行以及串行垃圾收集器都需要一个full GC来压缩老年代,而这个压缩动作需要扫描整个老年代空间。

  因为G1以每个分区为基础做垃圾收集操作,所以它适用于大尺寸的Java堆。垃圾收集工作的数量可以被限制在一个小范围的分区集合内,哪怕Java堆尺寸可能会相当大。

  G1暂停时间的最大来源是年轻代收集和混合收集,所以G1的设计目标之一就是允许用户设置GC暂停时间目标。G1会尝试通过调整Java堆尺寸大小的方式来满足设定的暂停时间目标。它会根据暂停时间目标自动调整年轻代的尺寸和总的Java堆尺寸。暂停时间目标越短,年轻代空间就越小,总的堆空间就越大,使得老年代空间相对就越大。

  G1的设计目标就是把必要的调整限定在设置最大的Java堆空间和指定GC暂停时间目标上。另外,G1还被设计成可以通过一个内部的启发式算法来做自我调整。在写这本书的时候,G1的启发式算法就是HotSpot GC开发活动开展的最活跃的地方。同样到写这本书时为止,G1也许会要求一些特定场景下的额外调优,不过开发优秀的启发式算法的先决条件已经具备并且前景很可观。至于如何对G1进行调优的建议。

  综上,对于大的Java堆来说,通过将Java堆拆分成一个个分区,G1会比其他垃圾收集器有更好的综合表现。在局部压缩的帮助下,G1解决了Java堆碎片,它的绝大部分工作都通过多线程的方式完成。

  截止到写这本文时,G1首要针对的是那些有合理短暂停的大尺寸Java堆的用例,当然还有那些正在使用CMS垃圾收集器的应用。也有计划用G1来处理吞吐量用例,但对于那些追求高吞吐量,同时能容忍更长GC暂停的应用来说,目前并行垃圾收集器是更好的选择。

  本文选自《Java性能调优指南》,点此链接可在博文视点官网查看此书。
                    
  想及时获得更多精彩文章,可在微信中搜索“博文视点”或者扫描下方二维码并关注。
                       

时间: 2024-09-30 09:50:26

Garbage First(G1)垃圾收集器的相关文章

详解 JVM Garbage First(G1) 垃圾收集器

前言    Garbage First(G1)是垃圾收集领域的最新成果,同时也是HotSpot在JVM上力推的垃圾收集器,并赋予取代CMS的使命.如果使用Java 8/9,那么有很大可能希望对G1收集器进行评估.本文详细首先对JVM其他的垃圾收集器进行总结,并与G1进行了简单的对比:然后通过G1的内存模型.G1的活动周期,对G1的工作机制进行了介绍:同时还在介绍过程中,描述了可能需要引起注意的优化点.笔者希望通过本文,让有一定JVM基础的读者能尽快掌握G1的知识点. 第一章 概述 G1(Garb

转 G1垃圾收集器入门

转自:http://blog.csdn.net/zhanggang807/article/details/45956325 最近在复习Java GC,因为G1比较新,JDK1.7才正式引入,比较艰难的找到一篇写的很棒的文章,粘过来mark下.总结这篇文章和其他的资料,G1可以基本稳定在0.5s到1s左右的延迟,但是并不能保证更低的比如毫秒级(金融场景,所以说涉及到钱的,对技术要求真高),号称zing可以(但是一般做到低延时,在其他方面肯定有所损耗,比如吞吐),但是没有实际去研究过这种.另外,G1

G1垃圾收集器入门

G1垃圾收集器概述 一步步介绍G1 G1收集器采用一种不同的方式来分配堆. 下面通过图解的方式一步步地讲述G1系统. 1. G1的堆内存结构 堆内存被划分为固定大小的多个区域. 每个heap区(Region)的大小在JVM启动时就确定了. JVM 通常生成 2000 个左右的heap区, 根据堆内存的总大小,区的size范围允许为 1Mb 到 32Mb. 2. G1 堆空间分配 实际上,这些区域(regions)被映射为逻辑上的 Eden, Survivor, 和 old generation(

JVM中的G1垃圾收集器

G1 垃圾收集器是Jdk7的新特性之一.Jdk7+版本都可以自主配置G1作为JVM GC选项: 作为JVM GC算法的一次重大升级.JDK7u后G1已相对稳定.且未来计划替代CMS.所以有必要深入了解下:不同于其他的分代回收算法.G1将堆空间划分成了互相独立的区块.每块区域既有可能属于O区.也有可能是Y区,且每类区域空间可以是不连续的(对比CMS的O区和Y区都必须是连续的).这种将O区划分成多块的理念源于:当并发后台线程寻找可回收的对象时.有些区块包含可回收的对象要比其他区块多很多.虽然在清理这

G1垃圾收集器和CMS垃圾收集器 (http://mm.fancymore.com/reading/G1-CMS%E5%9E%83%E5%9C%BE%E7%AE%97%E6%B3%95.html#toc_8)

参考来源 JVM 体系架构 堆/栈的内存分配 静态和非静态方法的内存分配 CMS 回收算法 应用场景 CMS 垃圾收集阶段划分(Collection Phases) CMS什么时候启动 CMS缺点 G1收集算法 G1的发展 分代垃圾回收瓶颈 G1使用场景 G1特点 G1堆内存的分配 G1的进程内存占用(Footprint) G1 收集器收集过程 G1命令行参数 记录G1的GC日志 G1性能调优 参考来源 http://blog.csdn.net/renfufei/article/details/

深入理解 Java G1 垃圾收集器--转

原文地址:http://blog.jobbole.com/109170/?utm_source=hao.jobbole.com&utm_medium=relatedArticle 本文首先简单介绍了垃圾收集的常见方式,然后再分析了G1收集器的收集原理,相比其他垃圾收集器的优势,最后给出了一些调优实践. 一,什么是垃圾回收 首先,在了解G1之前,我们需要清楚的知道,垃圾回收是什么?简单的说垃圾回收就是回收内存中不再使用的对象. 垃圾回收的基本步骤 回收的步骤有2步: 查找内存中不再使用的对象 释放

G1 垃圾收集器入门

G1 垃圾收集器入门 概览 目的 这个教程覆盖了如何使用G1垃圾收集器和它是怎样被Hotspot JVM使用的,你会学到G1收集器内部是如何工作的,使用G1时的一些关键命令行开关和记录它的操作的一些选项. 完成耗时 大约1小时 介绍 这个OBE(Oracle By Example)覆盖了Java里的Java虚拟机G1垃圾回收的基本概念,在OBE的第一部分, 在介绍垃圾收集器和性能时会附带提供JVM的概览.下一部分回顾一下Hotspot JVM的CMS收集器如何工作.然后,一步一步来指导使用Hot

GC垃圾回收 | 深入理解G1垃圾收集器和GC日志

来源:并发编程网链接:http://ifeve.com/深入理解G1垃圾收集器/ G1 GC是Jdk7的新特性之一.Jdk7+版本都可以自主配置G1作为JVM GC选项:作为JVM GC算法的一次重大升级.DK7u后G1已相对稳定.且未来计划替代CMS.所以有必要深入了解下: 不同于其他的分代回收算法.G1将堆空间划分成了互相独立的区块.每块区域既有可能属于O区.也有可能是Y区,且每类区域空间可以是不连续的(对比CMS的O区和Y区都必须是连续的).这种将O区划分成多块的理念源于:当并发后台线程寻

G1 垃圾收集器

概念先知 什么是垃圾回收 简单的说垃圾回收就是回收内存中不再使用的对象. 垃圾回收的基本步骤: 查找内存中不再使用的对象 释放这些对象占用的内存 查找内存中不再使用的对象 如何判断哪些对象不再被使用呢?有2个方法: 引用计数法 引用计数法就是如果一个对象没有被任何引用指向,则可视之为垃圾.这种方法的缺点就是不能检测到环的存在. 根搜索算法 根搜索算法的基本思路就是通过一系列名为"GC Roots"的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference

理解G1垃圾收集器日志

理解G1垃圾收集器日志 发表这个文章的目的是为了解释使用了G1垃圾收集器的一些跟踪和诊断选项而生成出来的垃圾收集日志的意义.我们来看一下使用一个提供最详细的信息级别的生产环境选项PrintGCDetails生成的输出日志.同时,我们也会看一下启用的两个诊断选项 -XX:+UnlockDiagnosticVMOptions . -XX:G1PrintRegionLivenessInfo 的输出信息,它们会打印出在标记周期末尾每个区域的活跃对象使用了总空间.占用大小和 -XX:+G1PrintHea