原文地址
Getting Started with the G1 Garbage Collectorhtml
本文介绍了如何使用G1垃圾收集器以及如何与Hotspot JVM一块儿使用的基础知识。您将了解G1收集器在内部的功能,使用G1的关键配置,以及G1收集器的操做日志选项。java
接近1小时web
本文涵盖了Java虚拟机(JVM)G1垃圾收集(GC)的基础知识。在本文的第一部分中,提供了JVM的概述以及垃圾收集和性能的介绍。接下来的您将回顾有关CMS收集如何在HotspotJVM工做原理。而后,一步一步地介绍在HotspotJVM上G1垃圾收集的工做原理。接下来,有一个章节介绍G1垃圾回收器可用的垃圾收集命令行选项。最后介绍G1收集器的日志。算法
如下是硬件和软件要求的列表:数据库
前提条件编程
在开始本教程以前,您应该:浏览器
Java是Sun公司于1995年首次发布的编程语言和计算平台。它是为Java程序(包括实用程序,游戏和商业应用程序)提供支持的基础技术。 Java遍及全球超过8.5亿台我的电脑,全球数十亿台设备,包括手机和电视设备。 Java由许多关键组件组成,做为一个总体建立了Java平台。缓存
当您下载Java时,您将得到Java运行时环境(JRE)。JRE由Java虚拟机(JVM),Java平台核心类和支持Java平台库组成。全部这三个都须要在您的计算机上运行Java应用程序。使用Java7,Java应用程序能够做为桌面应用程序从操做系统运行,也能够做为桌面应用程序运行使用Java Web Start从Web安装,或者做为浏览器中的Web Embedded应用程序(使用JavaFX)运行。服务器
Java是一种面向对象的编程语言,包括如下功能:网络
Java开发工具包(JDK)是开发Java应用程序的工具集合。使用JDK,您能够编译以Java编程语言编写的程序,并在JVM中运行它们。此外,JDK提供用于打包和分发应用程序的工具。
JDK和JRE共享Java应用程序编程接口(Java API)。 Java API是开发人员用来建立Java应用程序的预包装库的集合。JavaAPI提供了工具来完成许多常见的编程任务使开发变得更简单,包括字符串操做,日期/时间处理,网络和实现数据结构(例如列表,映射,堆栈和队列)。
Java虚拟机(JVM)是一种抽象计算机。 JVM是一个程序,看起来像写入要执行的程序的机器。这样,Java程序被写入同一组接口和库。每一个操做系统都有特定的JVM实现,将Java程转换成本地操做系统上运行的指令和命令。这样Java程序就实现了平台独立性。
第一个Java虚拟机的原型是Sun公司实现的,模拟了相似于当代我的数字助理(PDA)的手持设备托管的软件中的Java虚拟机指令集。 Oracle当前实现了移动端,桌面和服务器设备上的JVM。但Java虚拟机不承担任何特定的技术实现,主机硬件或主机操做系统。Java本质上不是解释型语言,但也能够经过将其指令集编译为CPU的指令集来实现。它也能够在微代码中或直接在CPU中实现。
JVM不关心Java变成语言,只有特定的二进制格式,类文件格式。类文件包含Java虚拟机指令(或字节码)和符号表以及其余辅助信息。可是,任何具备有效类文件表达功能的语言均可以有JVM托管。受到机器平台无关的吸引,其余语言的实现者能够将JVM转变为其语言的传送工具。
HotSpot JVM具备支持强大的功能的架构基础,并支持实现高性能和大规模可扩展性的能力。例如,HotSpot JVM JIT编译器能生成动态优化代码。换句话说,它们在Java应用程序运行时进行优化决策,并生成针对底层系统架构的高性能本地机器指令。此外,经过发展演进和持续的工程化,JVM的运行时环境和多线程垃圾收集器,即便是在最大的可用计算机系统,HotSpot JVM也可提供高可扩展性。
JVM的主要组件包括类加载器,运行时数据区和执行引擎。
与性能相关的JVM的关键组件在下图中高亮显示
在JVM调优性能时须要关注三个组件。堆是存储对象数据的地方,该区域由启动时选择的垃圾收集器进行管理。大多数调优选项涉及到大小调整堆,并根据状况选择最合适的垃圾回收器。JIT编译器也对性能有很大影响,但不多须要使用较新版本的JVM进行调优。
一般在调优Java应用程序时, 关注两个主要目标:响应性或吞吐量。随着教程的进行,咱们将回顾这些概念。
响应
响应是指应用程序或系统响应所请求的数据的速度。示例包括:
对于专一于响应性的应用程序,不能接受大的暂停时间。重点是在短期内做出回应。
吞吐量
吞吐量关注在特定时间内最大限度地提升应用程序的工做量。如何测量吞吐量的示例包括:
对于专一于吞吐量的应用,高暂停时间是能够接受的。因为高吞吐量的应用在较长时间内集中于基准测试,所以不须要考虑快速的响应时间
G1垃圾收集器是一种服务器端垃圾收集器,针对大内存的多处理器机器。它以高几率知足垃圾收集(GC)暂停时间目标,同时实现高吞吐量。Oracle JDK 7u4及更高版本中彻底支持G1垃圾回收器。 G1收集器专为如下类型应用而设计:
G1计划做为并行标记扫描收集器(CMS)的长期替代品。将G1与CMS进行比较,G1是更好的解决方案。第一个区别是G1是压缩型收集器。G1的压缩功能,足以彻底避免使用细粒度的空闲内存进行分配,而是依赖于regions。这大大简化了收集器,而且消除了大部分的潜在碎片问题。此外,G1比CMS收集器提供更可预测的垃圾回收暂停时间,并容许用户指定所需的目标暂停时间。
常规的垃圾收集器(串行,并行,CMS)都将堆结构分为三个部分:年轻代,老年代和固定大小的永久代。
全部JVM内存对象最终都在这三个部分中的一部分,而G1收集器采起不一样的方法。
堆被分红一组大小相等的区域,每一个是连续范围的虚拟内存。某些Regions被分配给和常规收集器同样的角色(eden区,survivor区,老年代),但他们没有固定的大小。这提供了更大的内存使用灵活性。
在执行垃圾收集时,G1以相似于CMS收集器的方式运行。G1执行并发的全局标记阶段来肯定整个堆中对象的活动性。标记阶段完成后,G1知道哪些区域大部分是空的。它首先收集这些区域,这一般产生大量的可用空间。这就是为何这种方式叫作垃圾收集优先。顾名思义,G1将其收集和压缩活动集中在可能充满可回收对象的堆区域,也就是垃圾。G1使用暂停预测模型来知足用户定义的目标暂停时间,并根据指定的目标暂停时间选择要收集的区域数量。
被G1标识成熟的区域是经过转移的方式收集。G1将对象从堆的一个或多个区域复制到堆上的单个区域,而且在此过程当中,同时压缩和释放内存。这种转移方法在并行运行在多处理器上,以减小暂停时间并提升吞吐量。于是,对于每一次垃圾收集,G1都不断地减小碎片,而且在用户定义的暂停时间内工做。这种方式超出了之前的两种方法(指CMS和ParallelOld)的能力。CMS垃圾收集器不执行内存压缩,ParallelOld垃圾收集器执行全堆压缩,这将致使很大的暂停时间。
一个值得注意的点,G1不是一个实时垃圾收集器。它尽量的符合设定的目标暂停时间,可是不能绝对实现。根据之前收集的垃圾时间,G1估计能够在用户指定的目标时间内收集多少个区域。所以,收集器具备收集区域的成本的至关准确的模型,而且使用该模型来肯定目标暂停时间内收集哪些区域和多少区域。
注意:G1同时有并发(与应用程序线程一块儿运行,例如细化,标记,清理)和并行(多线程,例如STW)的阶段。FullGC仍然是单线程的,可是若是您的应用程序正确调优,应避免使用Full GC。
若是从Parallel Old收集器或CMS收集器迁移到G1,则可能会看到更大的JVM进程大小。这主要与"accounting"数据结构相关,如Remembered Sets(RSets)和Collection Sets(CSets)。
G1的第一个重要特色是为用户的应用程序的提供一个低GC延时和大内存GC的解决方案。这意味着堆大小6GB或更大,稳定和可预测的暂停时间将低于0.5秒。
若是应用程序使用CMS或ParallelOld垃圾回收器具备一个或多个如下特征,将有利于切换到G1:
注意:若是你正在使用CMS或ParallelOld收集器,而且你的应用程序没有遇到长时间的垃圾收集暂停,则保持与您的当前收集器是很好的。升级JDK并没必要要更新收集器为G1。
CMS(也称为并发低暂停收集器)收集器是收集老年代垃圾的。它尝试经过与应用程序线程同时执行大部分垃圾收集工做来最小化因为垃圾回收引发的应用暂停时间。一般状况下,CMS不会复制或压缩存活的对象,完成一次垃圾收集不须要移动存活的对象。若是有内存碎片问题,须要分配一个较大的堆。
注意: CMS收集器在年轻代的收集与parallel收集器使用相同的算法
CMS收集器在老年代上执行如下阶段:
Phase | Description |
---|---|
(1)初始标记(STW) | 老年代对象被标记为可达,包括来自年轻代引用的对象;停顿时间相比于年轻代收集停顿时间更短 |
(2)并发标记 | 遍历老年代的可达对象,这个过程和应用线程并发执行;从标记的对象开始扫描,并将根目录中的全部可达对象进行标记。mutator在并发阶段2,3和5期间执行,而且在这一阶段CMS生成中分配的任何对象(包括年轻代晋升的对象)都将当即标记为存活。 |
(3)从新标记 (STW) | 并发标记阶段查找由于并发标记阶段应用线程产生的遗漏的对象(该阶段是暂停JVM的) |
(4)并发清理 | 收集在标记阶段收集标识为不可达的对象,死亡的对象被加到空闲列表供之后分配用,这一阶段可能会发生死亡对象的合并 注意:存活对象不会被移动 |
(5)重置 | 清除数据结构,准备下一次并发收集 |
备注(译者注):GC是JVM的一部分,mutator应该是JVM非GC的部分,职责是包括分配内存,read(从内存中读取内容),write(将内容写入内存)
接下来,咱们一步一步回顾CMS收集器操做
1. CMS收集器堆堆结构
JVM堆被分红三个空间
年轻代被分红eden和2个survivor区。老年代是一个连续的空间,对象在此收集。老年代会不进行压缩,除非有FullGC。
2. YongGC 是如何工做的
下图中绿色的是年轻代,蓝色的是老年代。这就是你的应用程序运行一阵子后,使用CMS收集器的外观,对象散落在老年代区域
使用CMS,老年代对象被从新分配。他们没有被移动,内存空间没有被压缩,除非有FullGC。
3. 年轻代收集
存活对象从Eden区和一个survivor区拷贝到另外一个survivor区,任何一个“年龄”达到阈值的对象会被晋升到老年代。
4. YoungGC以后
在YoungGC以后,Eden区和一个survivor区会被清理。
新晋升老年代的对象用深蓝色表示,绿色的对象是还未晋升老年代的年轻代对象。
5. 老年代垃圾收集 - CMS
有2个STW(Stop-The-World)事件发生:初始标记和从新标记。当老年代分配的对象达到必定的比例,CMS被触发
(1)初始标记是一个短暂的暂停阶段,其中标记存活(可到)对象。(2)并发标记会在应用程序执行的同时查找存活的对象。最后在从新标记的阶段(3),发如今上一阶段(2)并发标记期间遗漏的对象。
6. 老年代垃圾收集 - 并发清理
在前一阶段没有标记的对象会被释放,这一阶段没有压缩。
注意: 未标记的对象==死亡对象
7. 老年代垃圾收集 - 清理以后
在阶段(4)并发清理以后,你能看到不少内存被释放。同时你也注意到没有压缩整理动做
最后,CMS收集器将跳到复位阶段(5),等待下一次达到GC的阈值
G1收集器采用不一样的方法来分配堆。接下来的图将逐步回顾G1系统
1. G1堆结构
堆内存会被切分红为不少个固定大小区域
区域大小由JVM在启动时设置。 JVM一般针对2000个区域,大小从1到32Mb
2. G1 堆分配
实际上,这些区域在逻辑上被映射为Eden,Survivor和老年代
途中标记为不一样颜色的区域对应不一样的角色。存活的对象从一个区域转移(即复制或移动)到另外一个区域。区域被设计为并行收集垃圾,可能会暂停全部应用线程。
如图所示,区域能够分配到Eden,survivor和老年代。此外,还有第四种类型,被称为巨型区域(Humongous Region)。Humongous区域是为了那些存储超过50%标准region大小的对象而设计的,他们被存储在一系列的连续区域内,最后Humongous区域将是堆未使用的区域。
注意:在撰写本文时,收集Humongous对象还没有被优化。所以,您应避免建立此大小的对象。
3. G1的年轻代
堆被分红大约2000个区域,最小为1Mb,最大为32Mb。蓝色区域表示存储老年代的对象,绿色区域表示存储年轻代对象。
注意: 这些区域不像常规垃圾收集器须要连续
4. G1的YoungGC
存活的对象会被准转移(拷贝或移动)到1个或者多个survivor区域。若是到达了年龄阈值,一些对象会被晋级到老年代的区域。
这一阶段是暂停应用的(STW)。Eden和Survivor大小被计算下一次youngGC。统计信息有助于计算区域的大小,像目标暂停时间会被考虑到。这种方法使得很是容易调整区域的大小,根据须要变得更大或者更小。
5. G1 YoungGC结束
存活的对象已被转移到survivor区域或老年代
最近晋级的对象用深蓝色表示,survivor区域用绿色表示
关于G1年轻代的总结以下:
像CMS收集器,G1收集器设计的目标也是一个低暂停时间的老年代收集器。
G1收集器在老年代上收集分为如下阶段。注意,一些阶段也是年轻代收集的一部分
Phase | Description |
---|---|
(1) 初始标记(STW) | 这是一个STW的事件,使用G1,初始标记阶段会在YoungGC附带。标记survivor区域对象(根区域),它们可能引用到老年代对象 |
(2) 根区域扫描 | 扫描survivor区域对象引用了老年代对象。这一阶段和应用程序并发,必须在YoungGC以前完成 |
(3) 并发标记 | 在整个堆上查找活动对象,并发标记和应用程序并发进行。这一阶段能够被YoungGC打断 |
(4) 从新标记(STW) | 完成堆上全部存活对象的标记,使用一种叫snapshot-at-the-beginning (SATB) 的算法,该算法比CMS从新标记的算法高效不少 |
(5) 清理(STW和并发) | (1)执行存活对象和彻底空闲区域的统计(STW) (2)清空Remembered Sets(STW) (3)重置空闲区域并将它们返回到空闲列表(并发) |
(*) 拷贝(STW) | 这个阶段STW操做,转移和复制存活的对象到未使用的区域。这能够在年轻代执行,日志显示为[GC pause (young)]。或者同时在年轻代和老年代的区域执行,日志显示为[GC Pause (mixed)] |
注释(译者注):SATB算法是从新标记阶段对可能漏标的white对象进行快速标记的算法,详情请参考R大写的文章
在定义的阶段中,咱们来看看它们如何与G1收集器中的老年代进行交互。
6. 初始标记阶段
存活的对象的初始标记附带在YoungGC中。在日志中显示为GC pause (young)(inital-mark)
7. 并发标记阶段
若是找到空区域(被标记为“X”),它们在从新标记阶段马上被删除。此外,决定是否存活的统计信息会被计算。
8. 从新标记
空区域会被删除和回收,全部区域的存活信息会被统计。
9.复制/清理阶段
G1选择“活跃度最低”的区域,由于这些区域最快被收集。这些区域和YoungGC同时被收集。这在日志中显示为[GC pause (mixed)],因此年轻代和老年代同时被收集。
10. 复制/清理阶段以后
这些已被收集并整理的区域被表示为深蓝色和深绿色。
综上所述,关于G1老年代垃圾回收有几个要点
在本节中,咱们来看看G1的各类命令行选项。
要使G1收集器,须要配置-XX: +UseG1GC
如下是一个简单的命令行启动Java2Demo,包括JDK demos and 例子。
java -Xmx50m -Xms50m -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -jar c:\javademos\demo\jfc\Java2D\Java2demo.jar
-XX:+UseG1GC 告诉JVM使用G1垃圾收集器
-XX:MaxGCPauseMillis=200 设置GC的最大目标暂停时间。这是一个软性目标,JVM将尽力实现。所以,目标暂停时间的有时不必定能实现。默认值是200ms
-XX:InitiatingHeapOccupancyPercent=45 启动并发GC循环堆占用比例。G1基于整个堆的占用比例来触发并发GC循环。这个参数不只做用在一个代(年轻代和老年代都有效),默认值是45%
使用G1时,应遵循一些最佳实践
不要设置年轻代的大小
使用G1收集器的默认行为,经过-Xmn显示指定年轻代大小
请考虑设定值能知足90%以上的目标,而不是使用平均响应时间(ART)做为一个指标设置XX:MaxGCPauseMillis=N。这意味着90%的请求用户将不会遇到高于目标的响应时间。请记住,暂停时间是一个目标,不能保证始终获得知足。
对象晋级失败表示在GC期间JVM用完了堆区域,转移survivors区域和晋级对象失败。堆不能再扩展,由于它已是最大的了。配置参数-XX:+PrintGCDetails,经过观察空间溢出在GC日志中显示。可是代价很高!
为了不转移失败,考虑如下的措施:
增大堆大小
使用-XX:ConcGCThreads=n选项增长标记线程的数量
这是G1 GC开关的完整列表。请记得使用上述最佳实践
Option and Default Value | Description |
---|---|
-XX:+UseG1GC | G1收集器开关 |
-XX:MaxGCPauseMillis=n | 设置最大的目标暂停时间,这是一个软性目标,JVM蒋尽可能去实现 |
-XX:InitiatingHeapOccupancyPercent=n | 启动并发GC的Java堆占用阈值,用于触发GC周期,不只仅是触发一个代(例如G1)。值为0表示“始终启动GC循环”,默认值是45 |
-XX:NewRatio=n | 年轻代/老年代的比例,默认值是2 |
-XX:SurvivorRatio=n | eden/survivor比例,默认值8 |
-XX:MaxTenuringThreshold=n | 最大的老年代阈值,默认值15 |
-XX:ParallelGCThreads=n | 设置在垃圾回收器的并行阶段使用的线程数,默认值根据JVM平台而不一样 |
-XX:ConcGCThreads=n | 并发垃圾收集器将使用的线程数,默认值根据JVM平台而不一样 |
-XX:G1ReservePercent=n | 设置做为空闲空间的预留内存百分比,以下降晋级失败的可能性,默认值是10% |
-XX:G1HeapRegionSize=n | G1把Java堆细分红均匀大小的区域,这个参数设置region的大小。此参数的默认值根据堆的大小设置,最小值是1Mb最大值是32Mb |
最后一个主题咱们须要解决的是使用日志信息来分析G1收集器的性能。本节简要介绍可用于收集数据的开关和日志中打印的信息。
您能够设置为三个不一样级别的详细日志
(1) -verbosegc (至关于-XX:+PrintGC) 设置精简日志级别
样例输出
[GC pause (G1 Humongous Allocation) (young) (initial-mark) 24M- >21M(64M), 0.2349730 secs] [GC pause (G1 Evacuation Pause) (mixed) 66M->21M(236M), 0.1625268 secs]
(2) -XX:+PrintGCDetails 设置更详细的日志级别,该选项显示如下信息
(3) -XX:+UnlockExperimentalVMOptions -XX:G1LogLevel=最详细的日志级别,像PrintGCDetails级别,可是还包括每一个线程的信息。
[Ext Root Scanning (ms): 2.1 2.4 2.0 0.0 Avg: 1.6 Min: 0.0 Max: 2.4 Diff: 2.3] [Update RS (ms): 0.4 0.2 0.4 0.0 Avg: 0.2 Min: 0.0 Max: 0.4 Diff: 0.4] [Processed Buffers : 5 1 10 0 Sum: 16, Avg: 4, Min: 0, Max: 10, Diff: 10]
几个开关决定了GC日志中显示的时间
(1) -XX:+PrintGCTimeStamps - 显示自JVM启动以来通过的时间
样例输出
1.729: [GC pause (young) 46M->35M(1332M), 0.0310029 secs]
样例输出
[Ext Root Scanning (ms): Avg: 1.7 Min: 0.0 Max: 3.7 Diff: 3.7] [Eden: 818M(818M)->0B(714M) Survivors: 0B->104M Heap: 836M(4096M)->409M(4096M)]
(2)-XX:+ PrintGCDateStamps 为每一个条目添加时间前缀
2012-05-02T11:16:32.057+0200: [GC pause (young) 46M->35M(1332M), 0.0317225 secs]
为了理解GC日志,本节将使用实际GC日志输出定义一些术语。如下示例显示了日志的输出,其中包含您将在其中找到的术语和值的解释。
注意: 更多的日志信息,想查看Poonam Bajaj's Blog post on G1 GC logs
Clear CT
CSet
External Root Scanning
Free CSet
GC Worker End
GC Worker Other
Object Copy
Other
Parallel Time
Ref Eng
Ref Proc
Scanning Remembered Sets
Termination Time
Update Remembered Set
Worker Start
Parallel Time
414.557: [GC pause (young), 0.03039600 secs] [Parallel Time: 22.9 ms] [GC Worker Start (ms): 7096.0 7096.0 7096.1 7096.1 706.1 7096.1 7096.1 7096.1 7096.2 7096.2 7096.2 7096.2 Avg: 7096.1, Min: 7096.0, Max: 7096.2, Diff: 0.2]
Parallel Time – 主要的暂停平行部分的总耗时
Worker Start – worker线程开始的时间
注意: 日志按线程ID排序,每一个条目都一致
外根部扫描
[Ext Root Scanning (ms): 3.1 3.4 3.4 3.0 4.2 2.0 3.6 3.2 3.4 7.7 3.7 4.4 Avg: 3.8, Min: 2.0, Max: 7.7, Diff: 5.7]
External root scanning - 外根部扫描所花费的时间 (例如, 像系统字典那样的指向堆内的对象)
Update Remembered Set
[Update RS (ms): 0.1 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 Avg: 0.0, Min: 0.0, Max: 0.1, Diff: 0.1] [Processed Buffers : 26 0 0 0 0 0 0 0 0 0 0 0 Sum: 26, Avg: 2, Min: 0, Max: 26, Diff: 26]
Update Remembered Set - 已经完成收集可是还未被并发线程处理的,在暂停开始以前任何缓冲区须要被更新。耗时取决于卡表的密度,卡表越多,须要的时间越长。
Scanning Remembered Sets
[Scan RS (ms): 0.4 0.2 0.1 0.3 0.0 0.0 0.1 0.2 0.0 0.1 0.0 0.0 Avg: 0.1, Min: 0.0, Max: 0.4, Diff: 0.3]F
Scanning Remembered Sets - 扫描指向CSet的指针
Object Copy
[Object Copy (ms): 16.7 16.7 16.7 16.9 16.0 18.1 16.5 16.8 16.7 12.3 16.4 15.7 Avg: 16.3, Min: 12.3, Max: 18.1, Diff: 5.8]
Object copy – 每一个线程用于复制和转移对象的时间
Termination Time
[Termination (ms): 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 Avg: 0.0, Min: 0.0, Max: 0.0, Diff: 0.0] [Termination Attempts : 1 1 1 1 1 1 1 1 1 1 1 1 Sum: 12, Avg: 1, Min: 1, Max: 1, Diff: 0]
GC Worker End
[GC Worker End (ms): 7116.4 7116.3 7116.4 7116.3 7116.4 7116.3 7116.4 7116.4 7116.4 7116.4 7116.3 7116.3 Avg: 7116.4, Min: 7116.3, Max: 7116.4, Diff: 0.1] [GC Worker (ms): 20.4 20.3 20.3 20.2 20.3 20.2 20.2 20.2 20.3 20.2 20.1 20.1 Avg: 20.2, Min: 20.1, Max: 20.4, Diff: 0.3]
GC worker end time – 每一个GC工做线程中止的时间戳
GC worker time – 每一个GC工做线程的耗时
GC Worker Other
[GC Worker Other (ms): 2.6 2.6 2.7 2.7 2.7 2.7 2.7 2.8 2.8 2.8 2.8 2.8 Avg: 2.7, Min: 2.6, Max: 2.8, Diff: 0.2]
GC worker other - 不属于以前列的阶段的GC耗时(每一个GC线程),这些耗时应该很低。在过去,咱们看到该值过于高,并被归因于JVM其余部分的瓶颈(例如:逐层增长代码缓存占用率)
Clear CT
[Clear CT: 0.6 ms]
清理RSet扫描元数据表的时间
Other
[Other: 6.8 ms]
GC暂停的各类其余顺序阶段的耗时
CSet
[Choose CSet: 0.1 ms]
完成一系列regions收集的耗时;一般很是小;当选择清理老年代region会稍长一点
Ref Proc
[Ref Proc: 4.4 ms]
处理GC以前的阶段的soft,weak等引用的时间
Ref Enq
[Ref Enq: 0.1 ms]
处理soft,weak引用等待列表的耗时
Free CSet
[Free CSet: 2.0 ms]
释放刚被收集的regions集合的耗时,包括记录他们的集合(Cset)
本文中,您已经了解了G1垃圾回收器的概述。首先,你了解了堆和垃圾收集器是JVM的关键部分。而后,回顾了CMS和G1垃圾收集器的工做原理。而后,您学习了G1命令行以及使用它们的最佳实践。最后,您学习了GC日志中的对象和数据。
在本教程中,您已经了解到:
G1的相关和更多的信息,请参阅如下这些网站和连接: