【JVM技术指南】「GC内存诊断-故障问题排查」一文教你如何打印及分析JVM的GC日志(实战分析上篇)

一文教你如何打印及分析JVM的GC日志

  • JVM GC日志格式
  • JVM GC日志含义
    • JVM GC日志分析方法
      • 开启JVM-GC日志的启动参数
      • GC查看案例
        • JVM参数解析
        • 配置JVM参数
        • 对象是如何分配在Eden区
          • 内存区域分析
            • 初始化数组对象
    • 结论

当我们在开发Java应用程序时,JVM的GC(垃圾回收)是一个非常重要的话题。GC的作用是回收不再使用的内存,以便程序可以继续运行。在JVM中,GC的日志记录了GC的详细信息,包括GC的类型、时间、内存使用情况等。在本文中,我们将介绍JVM GC日志的格式、含义和分析方法。


JVM GC日志格式

JVM GC日志的格式通常是一系列以时间戳为基础的事件,每个事件都包含了GC的详细信息。以下是一个典型的JVM GC日志的示例:

2021-01-01T00:00:00.000+0800: 1.000: [GC (Allocation Failure) 1.000: 1024K->512K(4096K), 0.0010000 secs]

其中,时间戳的格式为[ISO 8601],GC类型为“GC (Allocation Failure)”,GC发生的时间为1.000秒,GC前后内存使用情况分别为1024K和512K,总内存为4096K,GC耗时为0.001秒。


JVM GC日志含义

JVM GC日志包含了大量的信息,可以帮助我们了解JVM的内存使用情况和GC的性能。以下是一些常见的GC日志含义:

  • GC类型:GC的类型,如“GC (Allocation Failure)”表示由于内存分配失败而触发的GC。
  • 时间戳:GC发生的时间戳,通常是以秒为单位的浮点数。
  • 内存使用情况:GC前后内存使用情况,包括已使用内存、总内存等。
  • GC耗时:GC的耗时,通常是以秒或毫秒为单位的浮点数。

JVM GC日志分析方法

JVM GC日志的分析可以帮助我们了解JVM的内存使用情况和GC的性能,以便优化应用程序的性能。以下是一些常见的JVM GC日志分析方法:

  • 使用GCViewer等工具:GCViewer是一款免费的GC日志分析工具,可以帮助我们可视化地分析JVM GC日志。使用GCViewer可以轻松地查看GC的类型、时间、内存使用情况等。

  • 分析GC日志文件:我们可以使用文本编辑器等工具来分析GC日志文件。通过分析GC日志文件,我们可以了解GC的类型、时间、内存使用情况等,以便优化应用程序的性能。

  • 调整GC参数:通过调整JVM的GC参数,我们可以优化GC的性能,以便提高应用程序的性能。例如,我们可以通过调整-Xmx和-Xms参数来调整JVM的堆大小,以便优化GC的性能。

开启JVM-GC日志的启动参数

  1. 如果需要打印GC日志,那么首先得把JVM-GC日志进行输出到本地文件,一般我们会在JVM启动的时候添加参数:

    • -XX:+PrintGCDetails:打印GC日志细节
    • -XX:+PrintGCTimeStamps:打印GC日志时间
    • -Xloggc:gc_view.log:将GC日志输出到指定的磁盘文件上去,这里会把gc.log输出到项目根路径
  2. 当JVM在运行过程中如果发生GC,那么将会把GC日志输出到gc_view.log中。

GC查看案例

JVM参数中加入GC日志的打印选型,jvm参数如下所示:

-XX:NewSize=5242880 -XX:MaxNewSize=5242880 -XX:InitialHeapSize=10485760 -XX:MaxHeapSize=10485760 -XX:SurvivorRatio=8 -XX:PretenureSizeThreshold=10485760 -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+
PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:gc.log

JVM参数解析

配置JVM参数

  • -XX:NewSize=5242880 : 初始新生代大小
  • -XX:MaxNewSize=5242880:最大新生代大小
  • -XX:InitialHeapSize=10485760:初始堆大小
  • -XX:MaxHeapSize=10485760:最大堆大小
  • -XX:SurvivorRatio=8:Eden区就是Survivor区的8倍,所以Eden区占4M,两个Survivor都是占0.5M。
  • -XX:MaxTenuringThreshold=15:那么新生代对象只有达到15岁才会进入老年代。
  • -XX:PretenureSizeThreshold=10485760:指定了大对象阈值是10MB,那么只有大于10M的对象才能直接在老年代分配
  • -XX:+UseParNewGC:使用ParNew
  • -XX:+UseConcMarkSweepGC:CMS垃圾回收器

  • -XX:+PrintGCDetails:打印详细的gc日志
  • -XX:+PrintGCTimeStamps:这个参数可以打印出来每次GC发生的时间
  • -Xloggc:gc.log:这个参数可以设置将gc日志写入一个磁盘文件。

对象是如何分配在Eden区

我们针对于上述代码的内存进行分析,最开始我们定义和初始化了字节数组:new byte[1024 * 1024],并且对于同一个引用,我们分配了3个相同大小的字节数组,每个数组都是1MB。

public static void main(String[] args) {
    byte[] arrayInit = new byte[1024 * 1024];
    arrayInit = new byte[1024 * 1024];
    arrayInit = null;
    //触发Young GC
    byte[] arrayInit2 = new byte[2 * 1024 * 1024];
}
内存区域分析
  1. 定义array1这个局部变量依次引用这三个对象,最后还把 array1 这个局部变量指向了null,那么在JVM中是如何运行的呢?
初始化数组对象
byte[] arrayInit = new byte[1024 * 1024];

在JVM的Eden区内存储一个1MB的对象,同时在main线程的栈中会压入一个main方法的栈帧,在main方法的栈帧内部,会有一个“arrayInit ”变量,这个变量是指向堆内存Eden区的那个1MB的数组。
在这里插入图片描述接着我们看第二行代码

arrayInit = new byte[1024 * 1024];

当执行了这行代码之后,便会在堆中的Eden区中再次分配一个数组,并且让之前的局部变量指向第二个数组,然后第一个数组就没人引用了,此时第一个数组就成了没人引用的“垃圾对象”了,如下图所示。
在这里插入图片描述接着我们来看第三行代码:array1 = null; 这行代码一执行,就让arrayInit 这个变量什么都不指向了,此时会导致之前创建的2个数组全部变成垃圾对象,如下图。
在这里插入图片描述在项目的根路径下,就可以看到一个gc.log,点进去查看:

0.383: [GC (Allocation Failure) 0.384: [ParNew: 3543K->512K(4608K), 0.0024598 secs] 3543K->1828K(9728K), 0.0026607 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
0.386: [GC (Allocation Failure) 0.387: [ParNew: 2627K->0K(4608K), 0.0015255 secs] 3943K->1828K(9728K), 0.0015985 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
Heap
 par new generation   total 4608K, used 2089K [0x00000000ff600000, 0x00000000ffb00000, 0x00000000ffb00000)
  eden space 4096K,  51% used [0x00000000ff600000, 0x00000000ff80a558, 0x00000000ffa00000)
  from space 512K,   0% used [0x00000000ffa00000, 0x00000000ffa00000, 0x00000000ffa80000)
  to   space 512K,   0% used [0x00000000ffa80000, 0x00000000ffa80000, 0x00000000ffb00000)
 concurrent mark-sweep generation total 5120K, used 1828K [0x00000000ffb00000, 0x0000000100000000, 0x0000000100000000)
 Metaspace       used 3101K, capacity 4620K, committed 4864K, reserved 1056768K
  class space    used 327K, capacity 392K, committed 512K, reserved 1048576K

从上面内容中可以看到进行了两次GC。

0.383: [GC (Allocation Failure)
0.384: [ParNew: 3543K->512K(4608K), 0.0024598 secs] 3543K->1828K(9728K), 0.0026607 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

从上面的内容可以得出:

  • 在第0.383秒,发生Allocation Failure,就是给对象分配内存的时候内存空间不够了,

    • [ParNew: 3543K->512K(4608K),0.0024598 secs]
      • 新生代的总内存大小为4608KB(4M的Eden区加上了 0.5M的Survivor From区,一共是4.5M,即4608M);
      • Young GC之前,新生代占用内存大小为3543KB(三个1M的数组,加上471KB的“未知内容”);
      • Young GC之后,剩余了512KB(“未知内容”)。
  • 在第0.384秒的时候,使用ParNew垃圾回收器进行了Young GC。

    • 3543K->1828K(9728K)
      • 整个堆内存大小为9728KB(即4M的Eden区加上0.5M的Survivor区加上5M的老年代大小,9.5M,即9728KB)。
      • 在Young GC之前,堆内存共有3543KB内存被占用(三个1M的数组,加上471KB的“未知内容”);
      • 在Young GC之后,堆内存共有1828KB。

0.386: [GC (Allocation Failure) 
0.387: [ParNew: 2627K->0K(4608K), 0.0015255 secs] 3943K->1828K(9728K), 0.0015985 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

之后输出了Young GC之后的堆内存使用快照:

Heap
 par new generation   total 4608K, used 2089K [0x00000000ff600000, 0x00000000ffb00000, 0x00000000ffb00000)
  eden space 4096K,  51% used [0x00000000ff600000, 0x00000000ff80a558, 0x00000000ffa00000)
  from space 512K,   0% used [0x00000000ffa00000, 0x00000000ffa00000, 0x00000000ffa80000)
  to   space 512K,   0% used [0x00000000ffa80000, 0x00000000ffa80000, 0x00000000ffb00000)
 concurrent mark-sweep generation total 5120K, used 1828K [0x00000000ffb00000, 0x0000000100000000, 0x0000000100000000)
 Metaspace       used 3101K, capacity 4620K, committed 4864K, reserved 1056768K
  class space    used 327K, capacity 392K, committed 512K, reserved 1048576K

可以看到新生代占用了2098KB(一个2M的数组,还有一点“未知内容”);Eden区被占用了51%,Survivor From和Survivor To使用率为0%,CMS管理的老年代被使用了1828KB。


结论

JVM GC日志是一个非常重要的话题,可以帮助我们了解JVM的内存使用情况和GC的性能。通过分析JVM GC日志,我们可以优化应用程序的性能,提高应用程序的稳定性和可靠性。

在这里,我向大家推荐一本关于JVM优化和调优的实战系列书籍,《深入浅出Java虚拟机 — JVM原理与实战》。这本书是最新出版的,内容涵盖了与我们当前工作和开发实例密切相关的技术和实战案例。通过学习这本书,我们可以深入了解Java虚拟机的原理,并通过实践掌握优化和调优的技巧。我诚挚地推荐这本书给大家,相信它将为我们的工作和技术发展带来巨大的收益。希望大家能够抽出时间多多学习一下这本宝贵的资料
在这里插入图片描述
【当当-点击链接】【京东-点击链接】

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/65096.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【PCL-6】PCL基于凹凸型的分割算法

凹凸型分割算法适用于颜色类似、棱角分明的物体场景分割。 算法流程&#xff1a; 1、基于超体聚类的过分割&#xff1b; 2、在超体聚类的基础上再聚类。 示例代码&#xff1a; //超体聚类LCCP //#include "stdafx.h"#include <stdlib.h> #include <cm…

分布式系统监控Zabbix

分布式系统监控Zabbix 一、Zabbix监控1.什么是Zabbix2.Zabbix功能3.Zabbix运行机制4.Zabbix的三种架构5.Zabbix工作原理及数据走向6.zabbix监控模式 二、Zabbix部署1.安装&#xff0c;部署准备2.zabbix图形化页面显示设置 三、Zabbix监控使用1.安装zabbix监控客户端2.服务端验证…

【第五章 flutter学习之flutter进阶组件-上篇】

文章目录 一、列表组件1.常规列表2.动态列表 二、FridView组件三、Stack层叠组件四、AspectRatio Card CircleAvatar组件五、按钮组件六、Stack组件七、Wrap组件八、StatefulWidget有状态组件总结 一、列表组件 1.常规列表 children: const <Widget>[ListTile(leading: …

从到店到到家,本土便利店正在围猎外资三巨头

全家在中国市场接连关店约300多家&#xff0c;7-11关闭或迁移全球市场的门店约1000家&#xff0c;罗森深圳公司2022年疑似亏损近8000万。 近三年来&#xff0c;以全家、7-11和罗森三家为代表的外资便利店企业&#xff0c;正在遭遇中国本土便利店品牌从到店到家的双重围猎。 20…

针对高可靠性和高性能优化的1200V碳化硅沟道MOSFET

目录 标题&#xff1a;1200V SiC Trench-MOSFET Optimized for High Reliability and High Performance摘要信息解释研究了什么文章创新点文章的研究方法文章的结论 标题&#xff1a;1200V SiC Trench-MOSFET Optimized for High Reliability and High Performance 摘要 本文详…

数据结构—图的存储结构

6.图 回顾&#xff1a;数据的逻辑结构 集合——数据元素间除 “同属于一个集合” 外&#xff0c;无其他关系。 线性结构——一个对一个&#xff0c;如线性表、栈、队列 树形结构——一个对多个&#xff0c;如树 图形结构——多个对多个&#xff0c;如图 6.1图的定义和术语 图:…

QT - 建立页面

一、生成页面 二、实现 1.LineEdit 是一个单行输入文本框&#xff0c;为用户提供了比较多的编辑功能&#xff0c;例如选择复制、粘贴。 修改echomode属性为password Push Button(常规按钮) 三、程序 声明全局变量&#xff0c;属于MainWindow private: // 定义了一个指向Ma…

使用vite创建Vue/React前端项目,配置@别名和Sass样式,又快又方便

Vite官方网站&#xff1a;Vite | 下一代的前端工具链 Vite 并不是基于 Webpack 的&#xff0c;它有自己的开发服务器&#xff0c;利用浏览器中的原生 ES 模块。这种架构使得 Vite 比 Webpack 的开发服务器快了好几个数量级。Vite 采用 Rollup 进行构建&#xff0c;速度也更快…

SAM 大模型Colab快速上手【Segment Anything Model】

Google Colab 是一个基于云的 Jupyter 笔记本环境&#xff0c;允许您通过浏览器编写、运行和共享 Python 代码。 它就像 Google 文档&#xff0c;但用于代码。 通过免费版本的 Google Colab&#xff0c;你可以获得带有约 16GPU VRAM 的 Nvidia Tesla T4 GPU&#xff0c;这对于…

SpringMVC的架构有什么优势?——表单和数据校验(四)

前言 「作者主页」&#xff1a;雪碧有白泡泡 「个人网站」&#xff1a;雪碧的个人网站 「推荐专栏」&#xff1a; ★java一站式服务 ★ ★ React从入门到精通★ ★前端炫酷代码分享 ★ ★ 从0到英雄&#xff0c;vue成神之路★ ★ uniapp-从构建到提升★ ★ 从0到英雄&#xff…

算法通关村——迭代实现二叉树的前中后序遍历

前言 递归就是每次执行方法调用都会先把当前的局部变量、参数值和返回地址等压入栈中&#xff0c;后面在递归返回的时候&#xff0c;从栈顶弹出上一层的各项参数继续执行&#xff0c;这就是递归为什么能够自动返回并执行上一层的方法的原因。因此&#xff0c;我们也可以模拟一个…

路由器工作原理(第二十九课)

路由器工作原理(第二十九课) 一图胜过千言 1) 路由:数据从一个网络到另外一个网络之间转发数据包的过程称为路由 2) 路由器:连接不同网络,实现不同网段之间的通信 3)路由表:路由器选择数据的传输路径的依据 原始的路由表 Destination/Mask Proto Pre Cost …

1706. 球会落何处;875. 爱吃香蕉的珂珂;1914. 循环轮转矩阵

1706. 球会落何处 核心思想&#xff1a;判断什么时候球会被卡住&#xff0c;1&#xff0c;当球在最左边的时候&#xff0c;挡板是向左的。2&#xff0c;当球在最右边的时候&#xff0c;挡板是向右的。3&#xff0c;当球当前的挡板是向左的&#xff0c;但是同一行的另一个挡板是…

【王树森】深度强化学习(DRL)课程笔记:P1 基本概念(含gym安装)

课程信息 课程主讲&#xff1a;王树森&#xff08;史蒂文斯理工学院计算机科学系的终身制助理教授&#xff09; 课程内容&#xff1a;基本概念、价值学习、策略学习、Actor-Critic方法、AlphaGo、Monte Carlo (蒙特卡洛) 课程资料&#xff1a;https://github.com/wangshusen/D…

用spinal写《自己动手写cpu》中的代码--pc_reg模块

一 预期代码 二 spinal代码 package oriimport spinal.core._class pc_reg(width: Int) extends Component{val io = new Bundle {val pc = out UInt(width bits)val ce = out UInt (1 bits)val clk = in Bool()val rst = in Bool()}val ceClkDomain = ClockDomain(clock = i…

html | 无js二级菜单

1. 效果图 2. 代码 <meta charset"utf-8"><style> .hiddentitle{display:none;}nav ul{list-style-type: none;background-color: #001f3f;overflow:hidden; /* 父标签加这个&#xff0c;防止有浮动子元素时&#xff0c;该标签失去高度*/margin: 0;padd…

小程序商品如何设置规格

商品规格是指商品在不同属性上的区分&#xff0c;比如颜色、尺寸、款式等。通过设置规格&#xff0c;商家可以更好地展示商品的多样性&#xff0c;并方便用户选择和购买。下面是怎么设置小程序产品规格的方法和步骤。 1. 添加/修改商品的时候&#xff0c;点击规格&#xff0c;会…

2、简单上手+el挂载点+v-xx(v-text、v-html、v-on、v-show、v-if、v-bind、v-for)

官网&#xff1a; vue3&#xff1a;https://cn.vuejs.org/ vue2&#xff1a;https://v2.cn.vuejs.org/v2/guide/ 简单上手&#xff1a; 流程&#xff1a; 导入开发版本的Vue.js <!--开发环境版本&#xff0c;包含了有帮助的命令行警告--> <script src"https…

Spring Boot整合ES的两种方式

使用Spring Data Elasticsearch Starter 在Spring Boot中整合Elasticsearch的方式之一是使用Elasticsearch的官方Spring Data Elasticsearch Starter。该Starter提供了对Elasticsearch的高级集成&#xff0c;简化了配置和管理Elasticsearch客户端。 下面是使用Spring Data E…

OnlyOffice社区版破解最大连接限制部署

onlyoffice社区版部署并且破解最大连接数 docker镜像 docker pull onlyoffice/documentserver:5.3.1.265.4或更高的版本已经解决了此方法的Bug 运行镜像 docker run -d --name onlyoffice --restartalways -p 暴露端口号:80 onlyoffice/documentserver:5.3.1.26进入容器内部…