G1垃圾回收器起步

JVM深度调优:深入 G1、ZGC 等新型垃圾回收器的适用场景与调优参数 JVM调优应围绕业务目标平衡吞吐、延迟和内存占用。G1适合4GB-几十GB堆的中等延迟需求场景,通过Region化堆和混合回收实现可控停顿;ZGC则针对大堆和极低延迟需求,采用并发压缩技术将停顿控制在1-2ms。调优需先明确目标(如在线交易侧重延迟,批处理侧重吞吐),通过GC日志分析症状(频繁GC、长停顿等),针对性调整关键参数(如G1的MaxGCPauseMillis、ZGC的ConcGCThreads)。建议从默认配置开始,基于日志数据逐步优化,优先考虑升级JVM版本而非过度调参。 阅读详情

感兴趣的朋友可以关注"猿学堂社区",系统化技术内容分享平台。或加入“猿学堂社区”微信交流群。
猿学堂师资均为一线互联网资深技术专家,提供专业、深度、体系化的技术课程,一站式技术解决方案。与技术专家线上线下深度互动、答疑解惑。在线学习笔记与课程完美结合。

原文地址

概述

目的

本教程涵盖了如何使用G1垃圾回收器以及G1如何与Hotspot JVM一起使用的基础知识。你将了解G1回收器内部的功能、用于启用G1的关键命令行开关以及输出G1操作日志的选项。

完成所需时间

大约1小时

介绍

本教程涵盖了JVM G1垃圾回收器的基础知识。第一部分提供了JVM概述以及垃圾回收和性能介绍。接下来回顾了Hotspot JVM中CMS垃圾回收器是如何工作的。然后,一步步指导在Hotspot JVM中使用G1回收器时,垃圾回收是如何工作的。在这之后,提供了一个小节涵盖了G1垃圾回收器与垃圾回收相关的命令行选项。最后,你将了解使用G1回收器时的日志选项。

软硬件需求

下面是一个软硬件需求列表:

  • 一个运行Windows XP或更高版本、Mac OS X或者Linux的PC。注意,操作这些操作在Windows7上完成,未在所有平台进行测试。尽管如此,在OS X或Linux应该工作正常。此外,可选择多核的机器。
  • Java 7 Update 9或更高版本
  • 最新的Java 7 Demo和Samples压缩文件

前提条件

开始该教程之前,你应该:

  • 如果未安装JDK,请下载并安装最新版本JDK(JDK 7 U9或更高)。
  • 下载并安装Demos和Samples压缩文件(与JDK下载在同一页面)。解压文件到个目录。例如:C:\javademos。

Java技术及JVM

Java概述

Java是一种编程语言和计算平台,由Sun公司首次发布于1995年。它是驱动Java程序包括工具、游戏、业务应用程序的基础技术。Java运行在全世界超过8亿5000万台个人电脑上以及全世界数十亿美元的设备,包括手机和TV设备。Java由一系列关键组件组成,作为一个整体创建Java平台。

JRE

当你下载Java,你将获得Java运行时环境(JRE)。JRE由JVM、Java平台核心类以及Java平台支持库组成。这三部分对于在你的电脑上运行Java应用是必须的。对于Java7,Java应用可以作为来自操作系统的桌面应用(译者注:Web应用+Servlet容器应属于该类)、使用JavaWeb Start从Web安装的桌面应用或者浏览器中的一个Web嵌入式应用运行(使用JavaFX)。

Java编程语言

Java是一种面向对象的编程语言,包含以下特征:

  • 平台独立——Java应用程序编译为字节码,存储在类文件中并由JVM加载。由于应用程序运行在JVM中,所以它们可以运行于许多不同的操作系统和设备上。
  • 面向对象——Java是面向对象的语言,采取了C和C++的许多特征并改善了它们。
  • 自动垃圾回收——Java自动分配和回收内存,因此应用程序不必承担该任务。
  • 丰富的标准库——Java包含了大量的预构建的对象诸如I/O、网络和日期操作等任务。

JDK

Java开发工具包(JDK)是一个Java应用程序开发工具集合。通过使用JDK,你可以编译Java编写的应用程序并在JVM中运行它们。除此之外,JDK提供了打包和发布应用的工具。

JDK和JRE共享Java应用程序接口(Java API)。Java API是开发人员用来创建Java应用的预先打包的库的集合。Java API通过提供工具来完成大部分常见的编程任务如字符串操作、日期/时间处理、网络操作和数据结构实现(如List、Map、Stack、Queue),使得开发更加简单。

JVM

JVM是一个抽象的计算机器。它是一个程序,像计算机一样,编写的程序可以在它里面运行。通过这种方式,Java程序可以编写为相同的接口和库的集合。对于针对具体操作系统的JVM实现,转换Java程序指令为本地操作系统的指令和命令。通过这种方式,Java程序实现了平台独立。

JVM的第一个原型实现由Sun公司完成,在类似于现在PDA这种手持设备的软件中模拟JVM指令集。Oracle现在已实现在手机、桌面和服务器设备上模拟JVM,但是JVM不承担任何特定的实现技术、主机的硬件或主机操作系统。它不是天生解释性的,但是也可以通过编译它的指令集到硅CPU上来实现。它还可以在微代码或直接在硅上实现。

Java虚拟机不知道Java编程语言的任何信息,除了一种特殊的二进制格式,即类文件格式。一个类文件包含了JVM指令集(或字节码)以及一个符号表和其它辅助信息。

为了安全起见,JVM对类文件中的代码施加了强语法和结构约束。不管如何,任何能够以一个有效的类文件进行描述的功能性语言都可以由JVM托管。吸引人的广泛应用、机器独立的平台,其它语言的实现者可以把JVM当做他们语言的载体。

JVM架构探索

HotSpot架构

HotSpot JVM的架构支持一个强大的功能和能力基础,支持实现高性能和大规模可伸缩性的能力。例如,HotSpot JVM JIT编译器生成动态优化。换句话说,它们在Java应用程序运行时制定优化策略并生成针对下层系统架构的高性能本地机器指令。此外,通过JVM运行环境的成熟演变和持续工程,HotSpot JVM具有高度可伸缩性,即使在最大的可用计算机系统中。

这里写图片描述

JVM的主要组件包括类加载器、运行时数据区域以及执行引擎。

关键Hotspot组件

与性能相关的JVM关键组件在下图中高亮显示:

这里写图片描述

调整性能时,JVM有三个组件需要关注。heap(堆)是对象数据存储的地方。该区域由启动时选择的垃圾回收器管理。大多数调整选项与堆大小以及为你的情况选择最合适的垃圾回收器有关。JIT编译器对于性能也有很大影响,但是对于新版本的JVM很少需要调整。

性能基础

通常,当优化Java应用时,主要关注两个目标中的一个:响应性或吞吐量。
我们将随着教程的进行,重新提及这些概念:

响应性

响应性是应用程序或系统使用请求数据进行响应的速度。
例子包括:

  • 桌面UI响应一个事件有多快
  • 网站返回一个页面有多快
  • 一次数据库查询有多快

关注响应性的应用,较大的暂停时间是不可接受的。因此,重点是在短时间内作出响应。

吞吐量

吞吐量关注在一段特定时间内使应用程序的工作量最大化。吞吐量如何测量的一些示例如下:

  • 给定时间内完成的事务数量
  • 一小时内一个批处理应用可以完成的任务数量
  • 一小时内可以完成的数据库查询次数

对于关注吞吐量的应用,高暂停时间是可以接收的。由于高吞吐量应用程序关注的是较长时间段内的基准,因此不考虑快速响应时间。

G1垃圾回收器

G1垃圾回收器

垃圾优先(G1)垃圾回收器是一个服务器类型的垃圾回收器,使用对象为多处理器、大内存的机器。它在实现高吞吐量的同时,以高概率满足垃圾回收器暂停时间的目标。Oracle JDK7 update 4及以后的版本完全支持G1垃圾回收器。G1垃圾回收器为以下应用设计:

  • 像CMS回收器一样可以与应用程序线程并发操作。
  • 压缩空闲空间而没有漫长的GC导致的暂停时间。
  • 需要更加可预测的GC暂停时间。
  • 不想牺牲大量吞吐量性能。
  • 不需要一个更大的Java堆。

G1计划作为CMS的长期替代品。比较G1与CMS,它们的差异使得G1称为一个更好的解决方案。一个区别是G1是压缩回收器,G1充分压缩,完全避免了使用细粒度空闲列表来进行分配,而是依赖于区域。这大大简化了回收器的部分工作,并且基本消除了潜在的碎片问题。此外,G1比CMS提供了更可预测的垃圾回收暂停,允许用户指定期望的暂停目标。

G1运行概况

旧的垃圾回收器(串行、并行、CMS)都将堆结构分为三部分:年轻代、年老代和以及一个固定内存大小的永久代(译者注:JDK8中,永久代已废弃)。

这里写图片描述

所有内存对象都在这三个部分中的一个终结。
G1垃圾回收器使用了不同的方法。

这里写图片描述

堆被划分为一组大小相等的堆区域,每个区域都是一个连续的虚拟内存范围。与旧的回收器中一样,某一区域组被分配为相同的角色(伊甸、幸存、年老),但是它们没有固定的尺寸。这给内存使用提供了更大的灵活性。

当执行垃圾回收时,G1以类似于CMS回收器的方式运行。G1执行一个并发的全局标记阶段,以确定整个堆中对象的活跃度。标记阶段完成之后,G1知道哪些区域大部分是空的。它先在这些区域回收,这样通常会产生大量的空闲空间。这是这种垃圾回收方法被称为Garbage-First(垃圾优先)的原因。顾名思义,G1将它的回收和压缩活动集中于可能充满可回收对象(即垃圾)的堆区域。G1使用一个暂停预测模型来满足用户定义的暂停时间目标并基于指定的暂停时间目标选择回收的区域数量。

G1识别为回收利用成熟的区域使用撤空进行垃圾回收。G1从堆中的一个或者多个区域拷贝对象到一个单独的区域,并在此过程中压缩和释放内存。这种撤空是在多处理器上并行执行的,以降低暂停时间并提升吞吐量。因此,通过每次垃圾回收,G1持续工作来减少碎片,并且在用户定义的暂停时间内工作。这超出了前面两种方法的能力。CMS垃圾回收器不进行压缩。并行年老代垃圾回收只执行整个堆的压缩,这导致相当大的暂停时间。

需要注意的是,G1不是实时回收器。它能大概率的满足设置的暂停时间目标。基于前面回收的数据,G1评估在用户指定的目标时间内可以回收多少个区域。因此,回收器有一个相当精准的回收区域成本的模型,它使用这个模型确定在暂停时间目标内,哪些以及多少区域会回收。

注意:G1既有并发(与应用程序线程一起运行,如净化、标记、清除),又有并行阶段(多线程,例如,stop-the-world)。完整的垃圾回收仍然是单线程的,但是如果调整得当,你的应用程序可以避免完整的垃圾回收。

G1占用空间

如果你从并行年老代回收或者CMS迁移到G1,你可能会看到更大的JVM进程大小。这在很大程度上与“记述(accounting)”数据结构诸如Remembered Set和Collection Set有关。

Remembered Set或RSet跟踪对象引用到一个给定区域。在堆中每个区域一个RSet。RSet使得区域并行独立的回收成为可能。RSet全部的占用空间影响小于5%。

Collection Set或CSet在一次垃圾回收中将要被回收的区域的集合。在垃圾回收过程中,所有CSet中的存活对象被撤空(拷贝/移动)。区域集合可能是伊甸、幸存和/或年老代。CSet对于JVM的大小的影响低于1%。

推荐G1的使用场景

G1的首要关注点是为用户运行那些需要大量堆但垃圾回收延迟有限的应用程序提供一个解决方案。这意味着堆大小为6GB或者更高,并且稳定和可预测的暂停时间低于0.5秒。

现在采用CMS或者并行年老代垃圾回收的应用程序将从切换到G1收益,如果应用程序有以下特征的一个或者多个:

  • 完整垃圾回收的持续时间太长或者太频繁
  • 对象分配率或者晋升(由年轻代移到年老代)率变化显著
  • 不期望的较长的垃圾回收或者压缩暂停(长于0.5到1秒钟)

注意:如果你正使用CMS或者并行年老代垃圾回收,并且你的应用没有经历长时间的垃圾回收暂停,它在当前的垃圾回收器下工作很好。那么,变更为G1垃圾回收器对使用最新版本的JDK并不是个要求。

回顾CMS垃圾回收

回顾代回收和CMS

CMS垃圾回收器(也被称为并发低暂停回收器)回收年老代。它尝试通过与应用程序线程并发执行大部分垃圾回收工作以尽量减少由于垃圾回收导致的暂停。通常并发低暂停垃圾回收器不会拷贝或者压缩存活对象。一次垃圾回收完成而不移动存活对象。如果碎片成为问题,分配一个更大的堆。

注意:CMS垃圾回收器对于年轻代使用与并行垃圾回收器相同的算法。

CMS回收阶段

CMS回收在堆的年老代执行以下阶段:

阶段描述
(1)初始标记(stop-the-world事件)年老代中的对象被“标记”为可达,包括那些可能从年轻代可达的对象。相对于minor回收(年轻代)暂停时间,该暂停时间通常持续时间较短。
(2)并发标记Java应用线程执行的同时,并发遍历年老代可达对象的对象图。从已标记的对象开始扫描,遍历标记所有从根节点可达的对象。修改器(指应用程序?)在2、3、5并发阶段执行,在这些阶段中CMS代分配的任何对象(包括提升的对象)被立即表为存活。
(3)重新标记(Remark)(stop-the-world事件)查找那些由于Java应用程序线程在并发回收器完成对对象的跟踪之后更新对象而导致并发标记阶段忽略的对象。
(4)并发清除回收标记阶段识别为不可达的对象。死对象的回收添加这个对象的空间到一个空闲列表,用于后续分配。此刻可能发生死对象合并。注意存活对象不会被移动。
(5)重置通过清除数据结构,为下一次并发回收做准备。

回顾垃圾回收步骤

接下来,让我们逐步回顾一下CMS垃圾回收器的操作。

1.CMS回收器的堆结构。
堆被分为三部分

这里写图片描述

年轻代被分为伊甸和两个幸存区。年老代是一个连续空间。对象回收适当的执行,不进行压缩,除非是一次完整垃圾回收。

2.CMS中年轻代如何工作

年轻代的颜色是浅绿色的,年老代是蓝色的。这是应用程序运行一段时间后,CMS可能看起来的样子。对象散布在年老代区域。

这里写图片描述

对于CMS,年老代对象被合适的释放。它们不会被到处移动。除非有完整的垃圾回收。否则空间不会被压缩。

3.年轻代回收

存活对象从伊甸区和幸存区拷贝到另一个幸存区。已经到达年龄阈值的所有较老的对象被提升到年老代。

4.年轻代回收之后

年轻代回收之后,伊甸区被清空并且一个幸存区也被清空。

新提升到年老代的对象在图中以深蓝色显示。绿色对象是还未提升到年老代的幸存的年轻代对象。

5.CMS中年老代回收

两次stop-the-world事件发生:初始标记和再次标记。当年老代达到某个占有率,CMS开始。

(1)初始标记是一个短暂暂停阶段,此时存活对象(可达)被标记。
(2)当应用程序继续执行时,并发标记查找存活对象。
(3)再次标记阶段,查找前面的(2)并发标记阶段遗漏的对象。

6.年老代回收——并发清除

在前一阶段中未被标记的对象释放。没有压缩。

注意:未标记对象==死对象

7.年老代回收——清除之后

在(4)清除阶段之后,你可以看到很多内存被释放了。你还要注意到没有进行压缩。

最后,CMS回收器将移到(5)重置阶段,等待下一次达到垃圾回收阈值。

G1垃圾回收器逐步说明

G1垃圾回收器逐步说明

G1垃圾回收器采用了不同的方法来分配堆。下面的图片按步回顾了G1系统。

1.G1堆结构

堆是一个内存区,拆分成许多固定大小的区域。

区域大小在启动时由JVM选择。JVM目标一般是2000个左右的区,通过从1MB到32MB调整区域大小。

2.G1堆分配

实际上,这些区域被映射为伊甸、幸存和年老代空间的逻辑表示。

图片中的颜色展示了哪个区域与哪个角色关联。存活对象从一个区撤空到另一个区(即复制或移动)。区域被设计为并行的回收,停止或者不停止所有其它应用程序线程。

如图所示,区域可能被分配到伊甸、幸存和年老代区。此外,还有第四种类型的对象,称为巨大区。这些区域被设计为持有大小为标准区域50%或者更大的对象。它们被存储为一组相邻的区域。最后一种类型的区域是堆中未使用的区域。

注意:在写这篇文章时,回收巨大对象无法优化。因此,应避免创建这种大小的对象。

3.G1中的年轻代

堆被分隔成大概2000个区域。最小大小为1MB,最大大小为32MB。蓝色区域持有年老代对象,绿色区域持有年轻代对象。

注意,区域不必像旧的垃圾回收器那样是连续的。

4.G1中的一次年轻代回收

存活对象被撤空(即如复制或移动)到一个或者多个幸存区域。如果到达年龄阈值,这些对象中的一些将提升到年老代区域。

5.G1中一次年轻代回收的结束

存活对象已经被撤空到幸存区域或者年老代区域。

最近提升的对象显示为深蓝色。幸存区域为绿色。

总之,关于G1中的年轻代,可以说明一下几点:

  • 堆是一个单独的内存空间,被拆分成了区域。
  • 年轻代内存由一组非连续的区域组成。这使得它在需要时非常容易调整。
  • 年轻代垃圾回收是stop-the-world事件。所有应用程序线程都停止。
  • 年轻代垃圾回收使用多线程并行进行。
  • 存活对象被拷贝到新的幸存区或者年老代区域。

G1中的年老代回收

类似于CMS回收器,对于年老代对象,G1回收器被设计成一个低暂停回收器。下表描述了在年老代G1回收的阶段。

G1回收阶段——并发标记周期阶段

G1回收器在堆的年老代执行以下阶段。注意某些阶段是年轻代回收的一部分。

阶段描述
(1)初始标记(stop-the-world事件)这是一个stop-the-world事件。对于G1,它是利用一个正常的年轻代回收。标记幸存区域(根区域),这些区域可能对年老代中的对象有引用
(2)根区域扫描扫描幸存区域,查找对年老代的引用。它在应用程序持续运行时发生。该阶段必须在一次年轻代回收可能发生之前完成。
(3)并发标记在整个堆查找存活对象。它在应用程序持续运行时发生。该阶段可能被年轻代垃圾回收打断。
(4)再次标记(stop-the-world事件)完成堆中存活对象的标记。使用一种称为snapshot-at-the-beginning(STAB)算法,它比CMS回收器中使用的算法快得多。
(5)清除(stop-the-world事件并且并发)执行存活对象的记述(accounting)并且完全释放区域(stop-the-world);擦掉RSet(stop-the-world);重置空的区域并将它们返回到空闲列表(并发)。
(*)复制(stop-the-world)stop-the-world暂停来撤空或复制存活对象到一个未使用的区域。这可能在年轻代区域完成,记录日志为[GC pause(young)]。或者在年轻代和年老代两类区域完成,记录日志为[GC Pause(mixed)]

G1年老代回收逐步说明

根据定义的阶段,让我们看一下在G1回收器中它们是如何与年老代交互的。

6.初始标记阶段

存活对象的初始标记利用了一次年轻代垃圾回收。在日志中,它注释为 GC pause (young)(inital-mark)

7.并发标记阶段

如果找到空的区域(标为“X”),它们在“再次标记阶段”被立即移除。此外,确定活跃度的“记述(accounting)”信息也被计算出来。

8.再次标注阶段

空区域被移除和回收。现在计算所有区域的区域活跃度。

9.复制/清除阶段

G1选择活跃度最低的区域,这些区域可以最快被回收。然后这些区域和年轻代回收同时被回收。这在日志中表示为[GC pause (mixed)]。因此年轻代和年老代两者同时被回收。

10.复制/清除阶段之后

被选择的区域已经被回收和压缩到深蓝色区域和深绿色区域,如图中所示。

年老代回收概述

总之,关于年老代垃圾回收有以下几个关键点:

  • 并发标记阶段
    • 活跃度信息在应用程序运行时并发计算
    • 活跃度信息确定哪些区域最适合于在撤空暂停阶段(evacuation pause)被回收
    • 没有像CMS的全面清扫(sweeping)阶段
  • 再次标记阶段
    • 使用snapshot-at-the-beginning(SATB)算法,比CMS中使用的算法更快
    • 完全空区域被回收
  • 复制/清除阶段
    • 年轻代和年老代同时被回收
    • 年老代区域根据它们的活跃度选择

命令行选项和最佳实践

命令行选项和最佳实践

在本节,让我们看一下G1的各种命令行选项。

基本命令行选项

启用G1垃圾回收器使用:-XX:+UseG1GC

下面是启动下载的JDK demo和sample中包含的Java2Demo的一个示例命令行:

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将尽最大努力来达到它。因此,暂停时间目标有时会无法满足。默认为200毫秒。

-XX:InitiatingHeapOccupancyPercent=45 启动一次并发垃圾回收周期时,整个堆的占用百分比。它被G1用来触发一次并发垃圾回收周期,基于整个堆的占用比,而不仅是某一个代。0标识“进行持续的垃圾回收周期”。默认值为45(即45%满或者占用)

最佳实践

使用G1时,你应该遵循一些最佳实践。

不要设置年轻代大小

显式的通过-Xmn设置年轻代大小会干涉G1垃圾回收器的默认行为。

  • G1将不再关注回收的暂停时间目标。所以本质上,设置年轻代大小会禁用暂停时间目标。
  • G1不能再根据需要扩展或者收缩年轻代空间。因为尺寸是固定的,所以不能改变。

响应时间指标

不要使用平均响应时间(ART)作为度量来设置XX:MaxGCPauseMillis=,而是考虑将值设置为满足90%的时间甚至更多的目标。这意味着90%的请求用户将不会体验到比目标更高的响应时间。记住,暂停时间是一个目标,并不能保证总是被满足。

什么是撤空失败?

当JVM在垃圾回收期间由于幸存或者提升对象耗尽堆区域时,会发生提升失败。堆由于已经最大,所以不能扩展。当使用了-XX:+PrintGCDetails时这会通过目的空间溢出(to-space overflow)体现在垃圾回收日志中。这很昂贵!

  • 垃圾回收仍然需要继续,因此空间必须被释放。
  • 未成功复制的对象必须适当的终结。
  • 对CSet中区域的RSet的任何更新必须再生。
  • 所有这些步骤都很昂贵。

如何避免撤空事变

为了避免撤空失败,考虑以下选项。

  • 增加堆内存
    • 增加-XX:G1ReservePercent=n,默认为10。
    • G1通过设法保留备用内存空闲来创建一个假上限,以防更多的"to-space"请求。
  • 较早启动标记周期
  • 使用-XX:ConcGCThreads=n选项增加标记线程的数目

G1垃圾回收开关的完整列表

下面是G1垃圾回收开关的完整列表。记住使用上面列出的最佳实践。

选项和默认值描述
-XX:+UseG1GC使用垃圾优先(G1)垃圾回收器
-XX:MaxGCPauseMillis=n设置一个最大GC暂停时间的目标。这是一个软性目标,JVM将尽最大努力来达到它。
-XX:InitiatingHeapOccupancyPercent=n启动一次并发垃圾回收周期时,整个堆的占用百分比。它被G1用来触发一次并发垃圾回收周期,基于整个堆的占用比,而不仅是某一个代。0标识“进行持续的垃圾回收周期”。默认值为45。
-XX:NewRatio=n年轻代和年老代大小的比例。默认为2。
-XX:SurvivorRatio=n伊甸和幸存空间大小的比例。默认为8。
-XX:MaxTenuringThreshold=n期限阈值的最大值。默认值为15。
-XX:ParallelGCThreads=n垃圾回收器并行阶段使用的线程数目。默认值随JVM运行的平台而异。
-XX:ConcGCThreads=n并发垃圾回收器使用的线程数目。默认值随JVM运行的平台而异。
-XX:G1ReservePercent=n作为虚假上限而保留的堆的数目,以减少提升失败的可能性。默认值为10。
-XX:G1HeapRegionSize=n对于G1,Java堆被分为大小相同的区域。该选项设置各区域的大小。它的默认值基于堆的大小确定,符合人类工程学。最小值为1MB,最大值为32MB。

使用G1时的垃圾回收日志

使用G1时的垃圾回收日志

我们需要讨论的最后一个主题是使用日志信息分析G1垃圾回收器的性能。本节提供了一个可以用来收集数据和打印日志信息的开关的快速概览。

设置日志详情

你可以将详情设置为三个不同等级。

(1)-verbosegc(等价于-XX:+PrintGC),将日志详细级别设置为fine。

示例输出

[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设置详细级别为finer。该选项显示以下信息:

  • 显示每一阶段的平均、最小、最大时间。
  • 根扫描、RSet更新(以及处理缓冲信息)、RSet扫描、对象复制、终止(以及尝试次数)。
  • 还显示“其它”时间,如选择CSet、引用处理、引用入队及释放CSet。
  • 显示伊甸、幸存和总的堆内存占用。

示例输出

[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)]

(3)-XX:+UnlockExperimentalVMOptions -XX:G1LogLevel=finest设置详细级别为finest。类似finer,但是包含独立的工作线程信息。

[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]

确定时间

一组开关用于确定在垃圾回收日志中时间如何显示。

(1)-XX:+PrintGCTimeStamps 显示自JVM启动后经过的时间。

示例输出

1.729: [GC pause (young) 46M->35M(1332M), 0.0310029 secs]

(2)-XX:+PrintGCDateStamps 为每条记录添加一个日期时间前缀。

2012-05-02T11:16:32.057+0200: [GC pause (young) 46M->35M(1332M), 0.0317225 secs]

理解G1日志

为了理解日志,本节使用实际的垃圾回收日志输出定义了若干术语。以下示例显示了日志中的输出,以及你将在日志中找到的术语和值的解释。

G1日志术语索引

  • 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排序,并且在每个条目都是一致的。

External Root Scanning

[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]

对象复制 — 每个独立线程复制和撤空对象花费的时间。

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]

Termination time — 当一个工作线程完成其特定对象集合的复制和扫描时,它将进入终止协议。它查找需要悄悄执行的工作,一旦完成该工作,它再次进入终止协议。“终止”尝试统计所有对执行工作的尝试。

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 – 当一个独立的垃圾回收Worker停止时的时间戳。

GC worker time – 一个独立的垃圾回收Worker线程花费的时间。

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 —不能归于前面列出的worker阶段的时间(对于每个线程)。应该相当低。在过去,我们曾经看到过极度高的值,它们被归于JVM其它部分的瓶颈(如,随着Tiered,代码缓存(Code Cache)占用的增加)。

Clear CT

[Clear CT: 0.6 ms]

用于清除RSet扫描元数据卡片表的时间。

Other

[Other: 6.8 ms]

垃圾回收暂停的其它顺序阶段花费的时间。

CSet

[Choose CSet: 0.1 ms]

最后确定要回收的区域集合所花费的时间。通常非常小;当必须选择年老代时,稍微长一些。

Ref Proc

[Ref Proc: 4.4 ms]

处理soft、weak等花费的时间。自垃圾回收先前阶段推迟的引用。

Ref Enq

[Ref Enq: 0.1 ms]

Time spent placing soft, weak, etc. references on to the pending list.
花费在放置soft、weak等的时间。在待定列表上的引用。

Free CSet

[Free CSet: 2.0 ms]

释放刚才回收的区域集花费的时间,包括它们的RSet。

总结

在本OBE,你获得了Java JVM中包含的G1垃圾回收器的一个概述。首先,你学会了堆和垃圾回收器是任何Java JVM中的关键部分。接下来,你回顾了CMS和G1的垃圾回收是如何工作的。然后,你了解了G1命令行开关和使用它们的最佳实践。最后,你了解了包含在垃圾回收日志中的对象和数据。

本教程中,你学会:

  • Java JVM的组件
  • G1垃圾回收器概述
  • CMS垃圾回收器回顾
  • G1垃圾回收器回顾
  • 命令行开关和最佳实践
  • G1中的日志

资源

对于更多信息,请查看以下网址和链接。

Credits

  • Curriculum Developer: Michael J Williams
  • QA: Krishnanjani Chitta
剖析G1 垃圾回收器 G1最大的特点就是非常重视高吞吐量与软实时性的最佳平衡,它让用户来设定期望最大暂停时间(Stop the word),也就是在垃圾回收时停止所有用户线程的时间,G1垃圾收集器可以预测下次 GC 会导致应用程序暂停多长时间。 阅读详情

相关推荐

大白话详解G1垃圾回收器

通俗语言讲解G1垃圾回收器通过分代管理和Region划分优化堆内存管理,采用三色标记法进行垃圾回收,支持动态调整内存和设置停顿时间。

不是很懂 3523

G1垃圾回收器步骤

4443.554: [GC pause (G1 Evacuation Pause) (young), 0.0061966 secs] [Parallel Time: 4.2 ms, GC Workers: 8] [GC Worker Start (ms): Min: 4443554.1, Avg: 4443554.2, Max: 4443554.2, Diff: 0.1] [Ext Root Scanning (ms): Min: 1.1, Avg: 1.2, Max: 1..

1205

JVM G1垃圾回收器详细解析

Garbage First(简称G1)收集器摒弃了传统垃圾收集器的严格的内存划分,而是采用了基于Region的内存布局形式和局部回收的设计思路。G1垃圾收集器把Java堆划分为2048个大小相等的独立的Region,每个Region大小取值范围为1-32MB,且必须为2的N次幂参数,可以通过-XX:G1HeapRegionSize设定,-XX:G1HeapRegionSize默认为0,此时Region的大小采用Java堆大小/2048的计算公式来确定,取值为最接近的2的N次幂数值。

阿坨的博客 2372

JVM学习之垃圾回收器

垃圾收集器没有在规范中进行过多的规定,可以由不同的厂商、不同版本的JVM来实现。由于JDK的版本处于高速迭代过程中,因此Java发展至今已经衍生了众多的GC版本。从不同角度分析垃圾收集器,可以将GC分为不同的类型。Java不同版本新特性语法层面:Lambda表达式、switch、自动拆箱装箱、enum、泛型API层面:Stream API、新的日期时间、Optional、String、集合框架底层优化:JVM优化、GC的变化、元空间、静态域、字符串常量池等。

BLF2 805

从叶片之舞到数据之眼:净空雷达如何重塑风电安全与效率的边界

净空雷达通过激光或毫米波技术实现风机叶片与塔筒间距离的毫米级实时监测,极大提升了风电场在极端天气下的安全性与运营效率。这项技术不仅预防扫塔事故,还通过数据可视化与智能分析赋能叶片健康管理和发电优化,成为风电数字化运维的核心基础设施。

xk7n92h3p5m的博客 1162

Cadence元件库介绍

Cadence安装完之后,在安装目录下,会有默认自带的一些常用元件库。例如,我的Candece安装目录为: D:\Cadence\Cadence_SPB_17.2-2016 元件库所在目录为: D:\Cadence\Cadence_SPB_17.2-2016\tools\capture\library 各个元件库对应的内容如下: AMPLIFIER.OLB 共 182 个零件,存放模拟放大器 IC,如 CA3280,TL027C,EL4093 等。 ARITHMETIC.OLB 共 182 个零件,存放

年少时的棉花糖 1万+

g1垃圾收集器gc的四种日志解释

g1垃圾收集器gc的四种日志解释

J_Lee 1598

LaTeX小白必看:5分钟搞定GB/T 7714-2005参考文献格式(Texmaker+BibTeX实战)

本文为LaTeX初学者提供了使用Texmaker编辑器和BibTeX工具链,快速实现GB/T 7714-2005参考文献格式的实战指南。文章详细解析了从获取gbt7714-2005.bst样式文件、编写.bib数据库到四步编译流程的核心步骤,并附有常见问题解决方案,帮助用户高效、准确地完成学术论文的参考文献排版。

weixin_29295541的博客 338

一文搞懂G1垃圾回收器

G1是从JDK9之后的默认垃圾回收器,其功能强大,性能优异,不过目前市面的材料不算多,很多都是抄来抄去,讲得也不太清楚。经过仔细阅读oracle官网以及相关的材料,从整体上梳理了G1的过程,希望这一文能帮你真正搞懂G1垃圾回收器。

纵横千里 捭阖四方 的专栏 4507

【可信数据空间-部署方案】

此部署架构体现了以下几个核心原则:去中心化: 数据存储和处理完全分布在各个参与者端,运营方只提供核心的协调和信任基础设施。安全边界清晰: 通过VPC、DMZ、防火墙、K8s命名空间等技术,在每个层级都建立了严格的安全边界。高可用与弹性: 所有关键服务均以集群方式部署,避免单点故障,并能根据负载动态伸缩。云原生: 全面采用容器化和Kubernetes编排,简化部署、管理和运维复杂度。合规性: 架构设计天然满足数据驻留要求(数据留在企业本地),并为所有操作提供不可篡改的审计追踪能力。

u014716614的博客 771

[ENVI]-[高光谱遥感]-波谱沙漏分析工具的使用

图1-2-1查看特殊波段的坏波段图1-2-2在中添加坏波段ENVI波谱沙漏分析工具MNF变换。

m0_57992372的博客 1470

G1垃圾收集器

[译]G1垃圾收集器 原文地址:Getting Started with the G1 Garbage Collector 原文作者:https://www.oracle.com 译文出自:https://github.com/cap-ljf/blog 本文永久链接:https://github.com/cap-ljf/blog/blob/master/tech/java/jvm/G1垃圾收集器...

cap_ljf 945

结构光之相移法+多频外差的数学原理推导

‍论文:基于数字光栅投影的结构光三维测量技术与系统研究 [博]作者:李中伟 华中科技大学 2007功能:相移法:多频外差(三频N步相移法)01 相移法图1 待写入投影仪的理想N步相移条纹通常对于 步相移来说,生成第 幅条纹图像(如图1所示)的公式如下:402 Payment Required其中::背景光强:调制强度:像素点横向坐标:相移值图2 相机拍摄到的实际 N ......

3D视觉工坊 1189

深入JVM:详解G1垃圾回收器原理

本文小豪将带大家认识各类垃圾回收器的基础概念与应用场景,同时重点讲解目前最为流行的G1垃圾回收器的工作原理。G1采用独特的内存管理策略,实现对整个堆空间的垃圾回收,主要将堆内存划分为多个大小相等的区域(称为Region),各个区域根据需要扮演不同的角色。G1垃圾回收器年轻代回收时,采用了三种关键技术,分别是记忆集、卡表和写屏障。

Code豪客 1万+

企业数字化建设之——品牌零售全渠道运营中台解决方案

OMS审单 --> 订单进入OMS待发货列表区域 --> 备货(线下)-->拣货((线下 )-->质检(线下)--> 包装(线下)--> 快递员取货(线下)(物品 + 客户收货地址清单 )--> 快递员发货(2.2.5 正常退货,客户发起 --> 客服助理审核 --> 评审组 --> ( 货物运输 ) -->质检 ->仓库收货入 正常仓库 -->财务退款,记账。OMS审单 --> 订单进入物流公司系统(如:*丰),--> 快递员发货 --> 物流状态同步OMS --> OMS同步物流状态到销售平台。

java_zhong1990的专栏 612

告警不是闹钟:AI 如何把告警过滤成真正的“求救信号”?

告警不是闹钟:AI 如何把告警过滤成真正的“求救信号”?

Echo_Wish 242

G1垃圾回收器详解

1. 概述 G1垃圾回收器是在Java7 update 4之后引入的一个新的垃圾回收器。G1是一个分代的,增量的,并行与并发的标记-复制垃圾回收器。它的设计目标是为了适应现在不断扩大的内存和不断增加的处理器数量,进一步降低暂停时间(pause time),同时兼顾良好的吞吐量。G1回收器和CMS比起来,有以下不同: G1垃圾回收器是compacting的,因此其回收得到的空间是连续的。这避免了...

傅红雪的专栏 2万+

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

CMS垃圾回收器和G1垃圾回收器区别

1.引言 我们知道java在C++语言的基础上演变而来。java垃圾回收机制是java和C++等语言的一个重要区别,让java程序员可以不用像C++程序员那样为内存回收而提心吊胆,而是专注于业务逻辑。在介绍垃圾回收机制之前我们首先要介绍下jvm。jvm是Java Virtual Machine(Java虚拟机)的缩写。 它是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机...

shlgyzl的博客 2万+

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

垃圾回收器之 G1 垃圾回收器

4.4 G1 定义:Garbage First 2004论文发布 2009 JDK 6u14 体验 2012 JDK 7u4 官方支持 2019 JDK9 默认 (废弃了之前的 CMS 垃圾回收器) G1取代了之前的CMS垃圾回收器 适用场景 同时注重吞吐量(Throughput)和低延迟(Low latency),默认的暂停目标是 200ms G1(读作 Garbage One)它是同时会注重吞吐量和低延迟,它的内部也是基于这种并发的,它也是一种 属于并发的垃圾回收器,跟我们之前提到的 CMS

qq_50313418的博客 1万+

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

G1垃圾回收器

G1垃圾回收器详解

weixin_50247953的博客 4831

G1垃圾回收器详细解读

最新的 G1 垃圾回收器 目录结构 1.G1垃圾回收器概述 2.设定内存大小 3.新生代垃圾回收 4.老年代垃圾回收 5.大对象回收分配策略 6. 混合垃圾回收 (Mixed-GC) 7. 总结 Parnew + CMS 的痛点: 无论是新生代还是老年代的垃圾回收,都会或多或少产生"stop the world" ,对系统运行有一定影响。而且不是可控的,只能优化。 1. G1垃圾回收器概述 G1 垃圾回收器可以同时回收新生代和老年代的对象,一个人负责所有。 内存结构: 把java堆内存拆分为多个大小相等的

qq_40662405的博客 9664

一文看懂:JVM垃圾回收算法、CMS垃圾回收器、G1垃圾回收器

Hello,大家好,我是此林。今天我们来聊一聊 JVM 垃圾回收机制。在C/C++这类没有自动垃圾回收机制的语言中,一个对象如果不再使用,需要手动释放,否则就会出现内存泄漏。内存泄漏指的是不再使用的对象在系统中未被回收,内存泄漏的积累可能会导致内存溢出。手动回收的方式相对来说回收比较及时,删除代码执行之后对象就被回收了,可以快速释放内存。缺点是对程序员要求比较高,很容易出现创建完对象之后,程序员忘记释放对象。

2401_82540083的博客 2512
上一篇: Java HotSpot VM内存管理白皮书
下一篇: Vert.x Java开发指南——第一章 介绍
边城白衣
博客等级 码龄14年 106粉丝 10原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值