我求求你了,GC日志打印别再瞎配置了
生产环境上,或者其他要测试 GC 问题的环境上,一定会配置上打印GC日志的参数,便于分析 GC 相关的问题。
但是可能很多人配置得都不够“完美”,要么是打印的内容过少,要么是输出到控制台,要么是一个大文件被覆盖,要么是……
本文带你一步一步,配置一个完美的 GC 日志打印策略
打印内容
为了保留足够多的“现场证据”,最好是把 GC 相关的信息打印的足够完整。而且你的程序真的不差你GC时打印日志I/O消耗的那点性能
打印基本 GC 信息
打印 GC 日志的第一步,就是开启 GC 打印的参数了,也是最基本的参数。
-XX:+PrintGCDetails -XX:+PrintGCDateStamps
打印对象分布
为了分析 GC 时的晋升情况和晋升导致的高暂停,不看对象年龄分布日志怎么行
-XX:+PrintTenuringDistribution
输出内容示例:
Desired survivor size 59244544 bytes, new threshold 15 (max 15)
- age 1: 963176 bytes, 963176 total
- age 2: 791264 bytes, 1754440 total
- age 3: 210960 bytes, 1965400 total
- age 4: 167672 bytes, 2133072 total
- age 5: 172496 bytes, 2305568 total
- age 6: 107960 bytes, 2413528 total
- age 7: 205440 bytes, 2618968 total
- age 8: 185144 bytes, 2804112 total
- age 9: 195240 bytes, 2999352 total
- age 10: 169080 bytes, 3168432 total
- age 11: 114664 bytes, 3283096 total
- age 12: 168880 bytes, 3451976 total
- age 13: 167272 bytes, 3619248 total
- age 14: 387808 bytes, 4007056 total
- age 15: 168992 bytes, 4176048 total
GC 后打印堆数据
每次发生 GC 时,对比一下 GC 前后的堆内存情况,更直观
-XX:+PrintHeapAtGC
输出内容示例:
{Heap before GC invocations=0 (full 0):garbage-first heap total 1024000K, used 324609K [0x0000000781800000, 0x0000000781901f40, 0x00000007c0000000)region size 1024K, 6 young (6144K), 0 survivors (0K)Metaspace used 3420K, capacity 4500K, committed 4864K, reserved 1056768Kclass space used 371K, capacity 388K, committed 512K, reserved 1048576K
Heap after GC invocations=1 (full 1):garbage-first heap total 1024000K, used 21755K [0x0000000781800000, 0x0000000781901f40, 0x00000007c0000000)region size 1024K, 0 young (0K), 0 survivors (0K)Metaspace used 3420K, capacity 4500K, committed 4864K, reserved 1056768Kclass space used 371K, capacity 388K, committed 512K, reserved 1048576K
}
打印 STW 时间
暂停时间是 GC 最重要的指标,肯定不能少
-XX:+PrintGCApplicationStoppedTime
输出内容示例:
Total time for which application threads were stopped: 0.0254260 seconds, Stopping threads took: 0.0000218 seconds
打印 safepoint 信息
进入STW阶段之前,需要要找到一个合适的 safepoint ,这个指标一样很重要(非必选,出现 GC 问题时最好加上此参数调试)
-XX:+PrintSafepointStatistics -XX:PrintSafepointStatisticsCount=1
输出内容示例:
vmop [threads: total initially_running wait_to_block] [time: spin block sync cleanup vmop] page_trap_count
0.371: ParallelGCFailedAllocation [ 10 0 0 ] [ 0 0 0 0 7 ] 0
Execute full gc...dataList has been promoted to cms old spacevmop [threads: total initially_running wait_to_block] [time: spin block sync cleanup vmop] page_trap_count
0.379: ParallelGCSystemGC [ 10 0 0 ] [ 0 0 0 0 16 ] 0 vmop [threads: total initially_running wait_to_block] [time: spin block sync cleanup vmop] page_trap_count
0.396: no vm operation [ 9 1 1 ] [ 0 0 0 0 341 ] 0
打印 Reference 处理信息
强引用/弱引用/软引用/虚引用/finalize 方法万一有问题,不得打印出来看看?
-XX:+PrintReferenceGC
输出内容示例:
2021-02-19T12:41:30.462+0800: 5072726.605: [SoftReference, 0 refs, 0.0000521 secs]
2021-02-19T12:41:30.462+0800: 5072726.605: [WeakReference, 0 refs, 0.0000069 secs]
2021-02-19T12:41:30.462+0800: 5072726.605: [FinalReference, 0 refs, 0.0000056 secs]
2021-02-19T12:41:30.462+0800: 5072726.605: [PhantomReference, 0 refs, 0 refs, 0.0000059 secs]
2021-02-19T12:41:30.462+0800: 5072726.605: [JNI Weak Reference, 0.0000131 secs], 0.4635293 secs]
完整参数
# requireds
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-XX:+PrintTenuringDistribution
-XX:+PrintHeapAtGC
-XX:+PrintReferenceGC
-XX:+PrintGCApplicationStoppedTime# optional
-XX:+PrintSafepointStatistics
-XX:PrintSafepointStatisticsCount=1
输出方式
上面只是定义了打印的内容,默认情况下,这些日志会输出到控制台(标准输出)。那如果你的程序日志也输出到控制台呢,这个日志内容就会很乱,分析起来很麻烦。如果你是追加的方式(比如 tomcat 的 catalina.out 就是追加),这个文件会越来越大,分析起来就要命了。
所以需要一种分割日志的机制,这个机制嘛……JVM自然是提供的。
JVM 的日志分割
JVM提供了几个用于分割 GC 日志的参数:
# GC日志输出的文件路径
-Xloggc:/path/to/gc.log
# 开启日志文件分割
-XX:+UseGCLogFileRotation
# 最多分割几个文件,超过之后从头开始写
-XX:NumberOfGCLogFiles=14
# 每个文件上限大小,超过就触发分割
-XX:GCLogFileSize=100M
按照这个参数,每个GC日志只要超过20M就会进行分割,最多分割5个文件,文件名依次是gc.log.0,gc.log.1,gc.log.2,gc.log.3,gc.log.4, …
看似很美好,几行配置就搞定了输出文件的问题。但是这种方式有一些问题:
- -Xloggc 方式指定的日志文件,是覆盖写的方式,每次启动都会覆盖,历史日志会丢失
- 当超过最大分割数后,会从第0个文件开始重新写入,而且是覆盖
- -XX:NumberOfGCLogFiles 并不能设置为无限
这个覆盖的问题就有点恶心了,每次启动覆盖之前的历史日志……这谁能忍?
使用时间戳命名文件
于是有另一种解决方案。不使用 JVM 提供的日志分割功能,而是每次启动用时间戳命名日志文件,这样可以每次启动都使用不同的文件,就不会出现覆盖的问题了。
# 使用-%t作为日志文件名
-XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/path/to/gc-%t.log# 生成的文件名是这种:gc-2021-03-29_20-41-47.log
可是这样就完美吗?
虽然没有覆盖的问题,但由于没有日志分割的功能,每次启动后只有一个GC日志文件,单个日志文件可能会非常巨大。过大的日志文件分析起来是很麻烦的,必须得分割。
二者结合
这里只需要稍微调整一下策略,将 JVM 分割和时间戳命名两种方案结合,就可以得到最优的方式了。
# GC日志输出的文件路径
-Xloggc:/path/to/gc-%t.log
# 开启日志文件分割
-XX:+UseGCLogFileRotation
# 最多分割几个文件,超过之后从头开始写
-XX:NumberOfGCLogFiles=14
# 每个文件上限大小,超过就触发分割
-XX:GCLogFileSize=100M
配置时间戳作文 GC 日志文件名的同时,也配置JVM的GC日志分割策略。这样一来,既保证了 GC 文件不会被覆盖,又保证了单个 GC 文件的大小不会过大,完美!
最终得到的日志文件名会像这个样子:
gc-2021-03-29_20-41-47.log.0
gc-2021-03-29_20-41-47.log.1
gc-2021-03-29_20-41-47.log.2
gc-2021-03-29_20-41-47.log.3
....
最佳实践 - 完整参数
# 必备
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-XX:+PrintTenuringDistribution
-XX:+PrintHeapAtGC
-XX:+PrintReferenceGC
-XX:+PrintGCApplicationStoppedTime# 可选
-XX:+PrintSafepointStatistics
-XX:PrintSafepointStatisticsCount=1# GC日志输出的文件路径
-Xloggc:/path/to/gc-%t.log
# 开启日志文件分割
-XX:+UseGCLogFileRotation
# 最多分割几个文件,超过之后从头文件开始写
-XX:NumberOfGCLogFiles=14
# 每个文件上限大小,超过就触发分割
-XX:GCLogFileSize=100M
### 最后**经过日积月累, 以下是小编归纳整理的深入了解Java虚拟机文档,希望可以帮助大家过关斩将顺利通过面试。**
由于整个文档比较全面,内容比较多,篇幅不允许,下面以截图方式展示 。如有需要获取资料文档的朋友,[可以点击这里免费获取](https://docs.qq.com/doc/DSmxTbFJ1cmN1R2dB)
![](https://img-blog.csdnimg.cn/img_convert/bbe3aba6b784f08071bc751ff1018526.png)
![](https://img-blog.csdnimg.cn/img_convert/a26c3bdb78e211bad7bf29c48509abe2.png)
![](https://img-blog.csdnimg.cn/img_convert/2c6164bc188da85d6cdb0222017b9cb6.png)
![](https://img-blog.csdnimg.cn/img_convert/27f28f98347c78f085d12176698291cf.png)
![](https://img-blog.csdnimg.cn/img_convert/34e14979d162e52b189593dd01bf5db5.png)
![](https://img-blog.csdnimg.cn/img_convert/1b06cd007537f2ed7270a610f7e96365.png)
![](https://img-blog.csdnimg.cn/img_convert/dc4be0e24b9558de6cb96a9296675506.png)]
[外链图片转存中...(img-SE2vtZh2-1623620366080)]
[外链图片转存中...(img-ODTPZG0T-1623620366081)]
[外链图片转存中...(img-KgjIGo2n-1623620366083)]
[外链图片转存中...(img-8vEr52x7-1623620366084)]
[外链图片转存中...(img-xwEeP61v-1623620366085)]**由于篇幅限制,文档的详解资料太全面,细节内容太多,所以只把部分知识点截图出来粗略的介绍,每个小节点里面都有更细化的内容!**
我求求你了,GC日志打印别再瞎配置了相关推荐
- 求求你了,配个GC日志呗,不然咋分析故障原因
点击关注公众号,Java干货及时送达 生产环境上,或者其他要测试 GC 问题的环境上,一定会配置上打印GC日志的参数,便于分析 GC 相关的问题. 但是可能很多人配置的都不够"完美" ...
- Java GC 日志解析
JVM 在Java应用程序优化中是不可缺少的一大重项,如何合理配置Java参数,如果验证配置参数的有效性,从GC日志中可以获得很重要的提示,以下是笔者对GC垃圾收集器默认开启的组合日志的部分的解析,希 ...
- 【Flink】Flink jvm参数配置GC日志
1.概述 转载:Flink jvm参数配置GC日志 生产环境上,或者其他要测试 GC 问题的环境上,一定会配置上打印GC日志的参数,便于分析 GC 相关的问题. 但是可能很多人配置的都不够" ...
- gc日志一般关注什么_理解GC日志
title: 理解GC日志 comments: false date: 2019-07-16 10:25:52 description: 理解 GC 打印的回收日志内容 categories: GC ...
- springboot 打印slf4_SpringBoot 整合 slf4j 日志打印
划水时间,记录一下用到的相关slf4j 日志打印,如何实现配置输出.本地保存log日志文件... 我使用的是SpringBoot框架,slf4j 类库已经包含到了 SpringBoot 框架中,所有, ...
- JVM实用参数 GC日志
为什么80%的码农都做不了架构师?>>> 原文章地址:http://blog.panaihua.com/archives/151 GC日志是一个很重要的工具,它准确记录了每一次 ...
- 教你如何通过分析GC日志来进行JVM调优
点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 不同的垃圾收集器产生的GC日志大致遵循了同一个规则,只是有 ...
- 两张图看懂GC 日志
GC日志查看 可以通过在java命令种加入参数来指定对应的gc类型,打印gc日志信息并输出至文件等策略. GC的日志是以替换的方式(>)写入的,而不是追加(>>),如果下次写入到同一 ...
- JVM GC 日志详解
本文采用的JDK版本: java version "1.8.0_144" Java(TM) SE Runtime Environment (build 1.8.0_144-b01) ...
最新文章
- Linux Redis 高可用之主从复制
- iBatis自动生成的主键 (Oracle,MS Sql Server,MySQL)【转】
- Access denied (java.lang.RuntimePermission getClas
- FLEX 动态添加事件
- HTML+CSS的学习
- CNN经典模型:GoogLeNet(从Inception v1到v4的演进)
- 为什么很多技术都觉得前端很简单?为什么?为什么?
- python遍历dataframe中的每个字符_pandas中遍历dataframe的每一个元素的实现
- 2019牛客暑期多校训练营(第四场)K-number
- TensorFlow变量:创建、初始化、保存和加载
- 【初识SciPy库】
- TCP实现消息传输和文件传输,UDP实现消息发送和聊天,URL下载文件
- dk 图解计算机科学pdf,DK英语:7套DK经典图解词典,再也不用死记硬背了!
- 纯JS写一个用苹果序列号查询生产信息的小工具
- 怎么戒网瘾?一个玩了上百款游戏的程序员告诉你有多少废话
- 童年学习机器人的 5 大好处
- 计算机应用基础实验报告心得体会,计算机应用基础实训总结报告
- 第一个被赋予公明身份的机器人_世界首位获公民身份机器人索菲亚,称要结婚生子毁灭人类...
- 基于51单片机的温度甲烷监测报警串口上报proteus仿真原理图PCB
- 3D Packing for Self-Supervised Monocular Depth Estimation
热门文章
- 2021年中国一次性医用传感器市场趋势报告、技术动态创新及2027年市场预测
- 蛋制品加工行业调研报告 - 市场现状分析与发展前景预测(2021-2027年)
- javascript java map_javascript实现java的map对象,js实现new map()
- 5W2H分析法,哪哪儿都能用到的方法,人生也可以套路进来
- mysql root 登录权限管理_MySQL基础教程(7)MySQL用户与权限管理
- 回溯 Rust 2020:正在成为最受欢迎的编程语言
- Hive 整合 HBase
- 红帽干掉 CentOS 8,CentOS Stream 上位
- 苹果正式发布自研 M1 处理器;神州数码回应:未与华为就荣耀出售达成任何协议​;Ant Design 4.8.1发布|极客头条
- 趣味图解 | 什么是缺页错误 Page Fault?