九、GC收集日志

本文涉及的产品
云解析 DNS,旗舰版 1个月
日志服务 SLS,月写入数据量 50GB 1个月
全局流量管理 GTM,标准版 1个月
简介: 九、GC收集日志


👋GC收集日志

⚽️1. 认识GC收集日志

垃圾收集日志是一个重要的信息来源,对于与性能相关的一些悬而未决的案例分析特别有用,例如它提供了一些关于崩溃发生原因的见解。它使得分析人员甚至可以在没有活跃的应用程序进程可供诊断的情况下开始工作。

每一个严肃的应用程序都应该始终做到:

• 生成垃圾收集日志;

• 将其保存在一个与应用程序的输出独立的文件中。

对于生产型应用程序来说尤其如此。正如我们将看到的,垃圾收集日志并没有明显可观测到的开销,所以对于任何重要的 JVM进程来说,它应该始终开启。

⚾️1.1 开启垃圾收集日志记录

首先要做的是在应用程序启动时添加一些开关。最好把这些开关看作必须打开的垃圾收集日志标志,任何 Java/JVM 应用程序(也许桌面应用程序可以除外)都应该启用。这些标志是:

-Xloggc:gc.log -XX:+PrintGCDetails -XX:+PrintTenuringDistribution
-XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps

接下来详细了解一下这些标志,其用法如下表所示。

性能工程师应该注意到关于这些标志的以下一些细节。

• PrintGCDetails 标志取代了比较旧的 verbose:gc 标志。应用程序应该删除原来的标志。

• PrintTenuringDistribution 标志与其他标志不同,因为它提供的信息人很难直接处理,需要使用工具。该标志提供了计算关键的内存压力影响和事件(如过早晋升)所需的原始数据。

• PrintGCDateStamps 和 PrintGCTimeStamps 都是必需的,因为前者用于将垃圾收集事件与应用程序事件(在应用程序日志文件中)相关联,后者用于将垃圾收集和其他内部JVM 事件相关联。

这种细节程度的日志记录不会对 JVM 的性能产生可测量的影响。当然,产生日志的量取决于许多因素,包括分配率、使用的收集器和堆大小(堆越小,则需要更频繁地进行垃圾收集,因此生成日志的速度也越快)。

除了必须使用的这些标志之外,还有一些控制垃圾收集的日志滚动的标志,许多应用程序支持团队会发现它们在生产环境中很有用。

要设置合理的日志滚动策略,应该与运维人员(包括 DevOps 人员)一起讨论决定。这种策略的选择以及对恰当的日志和工具的讨论不在本书范围之内。

⚾️1.2 垃圾收集日志与JMX的对比

在之前的文章中曾介绍过 VisualGC 工具,它能够实时显示 JVM 的堆状态。该工具实际上依靠JMX(Java Management eXtension)接口来收集 JVM 的数据。关于 JMX 的完整讨论就不扩展了,有兴趣的朋友可以去官网查看技术文档,但就 JMX 对垃圾收集的影响而言,性能工程师应该注意以下几点。

• 垃圾收集日志数据是由实际的垃圾收集事件驱动的,而 JMX 的来源数据是通过采样获得的。

• 垃圾收集日志数据获取的成本极低,而 JMX 存在隐含的代理和远程方法调用(remotemethod invocation, RMI)成本。

• 垃圾收集日志数据包含了与 Java 内存管理相关的性能数据的 50 多个方面,而 JMX 只有不到 10 个。

传统上,作为性能数据的来源, JMX 优于日志的一个方面是它可以提供开箱即用的流式数据。

通过 JMX 获得的 Bean 是标准化的,而且很容易访问。 VisualVM 工具提供了一种将该数据可视化显示的方式,市场上也有很多其他工具可用。

⚾️1.3 JMX的缺点

使用 JMX 监控应用程序的客户端,通常要依赖对运行时进行采样以获得当前状态的更新。为了连续获得数据,客户端需要轮询运行时中的 JMX Bean。

在存在垃圾收集的情况下,这会导致一个问题:客户端无法知道收集器何时运行,进而也意味着每个收集周期前后的内存状态都是未知的。因此,我们无法对垃圾收集数据执行一系列更深入和更精确的分析技术。

即便如此,基于 JMX 数据的分析仍然有用,但仅限于确定长期趋势。然而,如果想准确地调优某个垃圾收集器,我们需要做得更好。特别是能够了解每次收集前后堆的状态是非常有用的。

此外,还有一组围绕内存压力的极其重要的分析(即分配率)也因为从 JMX 收集数据的这种方式而不再能够执行。不仅如此, JMXConnector 规范目前的实现依赖于 RMI。因此,使用 RMI 通信通道会遇到的任何问题,使用 JMX 也同样会遇到。具体包括:

• 打开防火墙中的端口,以便可以建立后续的套接字连接;

• 使用代理对象以方便调用 remove() 方法;

• 依赖于 Java 终结化(finalization)。

对于少数 RMI 连接来说,关闭连接所需的工作量微乎其微。然而, 清理工作要依赖于终结化。这意味着必须运行垃圾收集器以回收该对象。

JMX 连接的生命周期这一性质在大多数情况下会导致 RMI 对象直到一次 Full GC 时才会被收集。

默认情况下,任何使用 RMI 的应用程序每小时都会触发 Full GC。对于已经使用 RMI 的应用程序,使用 JMX 不会增加成本。但是,对于还没有使用 RMI 的应用程序,如果决定使用 JMX,必然存在额外的影响。

⚾️1.4 垃圾收集日志数据带来的好处

现代的垃圾收集器包含了很多不同的活动部件,将其组合在一起得到的是一个非常复杂的实现。实现如此复杂,以致某个收集器的性能即使不是不可能的,也是很难预测的。这些类型的软件系统就是所谓的浮现式的(emergent),因为它们的最终行为和性能是所有组件如何共同工作和执行的结果。不同的压力会以不同方式影响不同的组件,从而导致成本模型也会动态发生变化。

最初, Java 垃圾收集的开发人员添加了垃圾收集日志来帮助调试其实现,因此, 60 个左右的垃圾收集相关标志所产生的数据中,有很大一部分是出于性能调试的目的。随着时间的推移,负责对应用程序中的垃圾收集过程进行调优的人开始意识到,鉴于垃圾收集调优的复杂性,对运行时中正在发生的事情有个精确的了解也会让他们受益匪浅。因此,不管采用何种调优方式,能够收集和阅读垃圾收集日志都是很有帮助的。

垃圾收集日志是在 HotSpot JVM 内部使用非阻塞写入机制来完成的。它对应用程序的性能没有影响,所有生产环境中的应用程序都应该开启垃圾收集日志。

⚽️日志解析工具

不同于语言规范和虚拟机规范,垃圾收集日志消息并没有一个标准的格式。 HotSpot 垃圾收集开发团队可以自行决定任何一条消息的内容。不同的小版本之间,格式都有可能发生改变,而且确实存在改变的情况。

虽然最简单的日志格式很容易解析,但随着垃圾收集日志标志的添加,所产生的日志输出就变得更为复杂了,因而情况也就进一步复杂化。并发收集器生成的日志更是如此。经常有这样的情况发生,即系统采用了手写的垃圾收集日志解析器,而有人修改了垃圾收集配置,这使得日志输出格式发生了变化,从而导致在此之后的某个时间点,解析器不能继续工作。调查其原因,矛头指向了垃圾收集日志,团队发现自己开发的解析器无法处理改变后的日志格式——解析器在日志信息最有价值的那个点停止了工作。

不建议开发人员自己解析垃圾收集日志。相反,应该使用某个工具。

⚾️2.1 GCViewer

GCViewer 是一个桌面工具,提供了一些基本的垃圾收集日志解析和图形化显示功能,其最大的优点在于它是开源软件,可以免费使用。然而,它提供的功能没有商业工具那么多。要使用 GCViewer,需要下载源代码。在编译和构建后,可以将其打包成一个可执行的 JAR文件。

然后可以在 GCViewer 主界面中打开垃圾收集日志文件,示例如下图所示。

GCViewer 缺乏分析能力,对于 HotSpot 可能生成的各种垃圾收集日志格式,它只能解析一部分。

可以将 GCViewer 用作解析库,将数据点导出到一个可以可视化显示的工具中,但这需要在现有开源代码的基础上进行额外的开发。

⚽️总结

本章重点介绍了 垃圾收集日志相关知识和工具的使用。

👬 交友小贴士:

博主GithubGitee同名账号,Follow 一下就可以一起愉快的玩耍了,更多精彩文章请持续关注。

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
15天前
|
存储 监控 Java
JVM进阶调优系列(8)如何手把手,逐行教她看懂GC日志?| IT男的专属浪漫
本文介绍了如何通过JVM参数打印GC日志,并通过示例代码展示了频繁YGC和FGC的场景。文章首先讲解了常见的GC日志参数,如`-XX:+PrintGCDetails`、`-XX:+PrintGCDateStamps`等,然后通过具体的JVM参数和代码示例,模拟了不同内存分配情况下的GC行为。最后,详细解析了GC日志的内容,帮助读者理解GC的执行过程和GC处理机制。
|
1月前
|
Arthas 监控 Java
JVM知识体系学习七:了解JVM常用命令行参数、GC日志详解、调优三大方面(JVM规划和预调优、优化JVM环境、JVM运行出现的各种问题)、Arthas
这篇文章全面介绍了JVM的命令行参数、GC日志分析以及性能调优的各个方面,包括监控工具使用和实际案例分析。
43 3
|
1月前
|
存储 数据可视化 安全
一个简单案例,带你看懂GC日志!
一个简单案例,带你看懂GC日志!
一个简单案例,带你看懂GC日志!
|
4月前
|
算法 安全 Java
(七)JVM成神路之GC分代篇:分代GC器、CMS收集器及YoungGC、FullGC日志剖析
在《GC基础篇》中曾谈到过分代以及分区回收的概念,但基础篇更多的是建立在GC的一些算法理论上进行高谈阔论,而本篇则重点会对于分代收集器的实现进行全面详解,其中会涵盖串行收集器、并行收集器、三色标记、SATB算法、GC执行过程、并发标记、CMS收集器等知识,本篇则偏重于分析GC机制的落地实现,也就是垃圾收集器(Garbage Collector)。
110 8
|
5月前
|
Java
GC日志打印
可以看到所有的FULL GC已经没有了,时间节省上面,大于是 0.03*3 约等于 0.1秒。
44 0
|
6月前
|
算法 Java
深入理解JVM - 解读GC日志
深入理解JVM - 解读GC日志
91 0
|
6月前
|
存储 Java
jvm性能调优实战 - 23 模拟Young GC的发生及分析GC日志
jvm性能调优实战 - 23 模拟Young GC的发生及分析GC日志
106 0
|
Java
JVM学习笔记-如何在IDEA打印JVM的GC日志信息
若要在Idea上打印JVM相应GC日志,其实只需在Run/Debug Configurations上进行设置即可。
114 0
|
缓存 安全 Java
JVM中垃圾回收相关参数介绍:大页和NUMA参数+GC日志相关参数
大页和NUMA参数 本节介绍JVM为使用OS而提供的大页和NUMA特性相关的参数。 该参数控制JVM向OS请求内存时使用大页的粒度。使用该参数时需要对OS进行配置,只有OS允许时才能真正启动。参数的默认值与平台相关,一般为false。 在允许使用大页方式向OS请求内存时,如果堆空间小于该阈值,则强制禁止大页使用。该参数的默认值为128MB。 在允许使用大页方式向OS请求内存时,优先在本地节点进行分配。该参数仅适用于Windows系统。 在允许使用大页方式向OS请求内存时,如果OS提供了多种大页的设置,可通过该参数选择其中的大页设置。参数的默认值为0,表示使用OS默认的大页设置。
177 0
|
11天前
|
XML 安全 Java
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
本文介绍了Java日志框架的基本概念和使用方法,重点讨论了SLF4J、Log4j、Logback和Log4j2之间的关系及其性能对比。SLF4J作为一个日志抽象层,允许开发者使用统一的日志接口,而Log4j、Logback和Log4j2则是具体的日志实现框架。Log4j2在性能上优于Logback,推荐在新项目中使用。文章还详细说明了如何在Spring Boot项目中配置Log4j2和Logback,以及如何使用Lombok简化日志记录。最后,提供了一些日志配置的最佳实践,包括滚动日志、统一日志格式和提高日志性能的方法。
117 30
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板