一次Jvm old过高的排查过程实战记录
作者:小草莓子桑 发布时间:2023-05-07 23:33:49
前言
最近遇到一个Jvm old过高的案例,现象是一个站点的jvm old区过高,分析原因是,原来的设计方案有问题,给前端返回的数据里面包含了大量的html代码,从存储中拿数据的过程、拼接数据的过程过于漫长了,造成了大量对象的生命周期过长,对象被 标记到了old中,造成了old区过高,监控系统进行了报警,详细原因就不做详细分析了,主要分享一下问题排查的过程。
收到了监控系统的报警,在服务器上查询jvm内存情况
jstat -gcutil pid 时间间隔,可以按时间间隔打印jvm的内存情况,例如:
jstat -gcutil 30922 1000
jvm进程30922的内存情况
大致说一下,S0,S1这些的含义:
S0:年轻代中第一个survivor(幸存区)已使用的占当前容量百分比
S1:年轻代中第二个survivor(幸存区)已使用的占当前容量百分比
E: 年轻代中Eden(伊甸园)已使用的占当前容量百分比
O: old代已使用的占当前容量百分比
P: perm代已使用的占当前容量百分比
YGC: 从应用程序启动到采样时年轻代中gc次数
YGCT:从应用程序启动到采样时年轻代中gc所用时间(s)
FGC: 从应用程序启动到采样时old代(全gc)gc次数
FGCT:从应用程序启动到采样时old代(全gc)gc所用时间(s)
GCT: 从应用程序启动到采样时gc用的总时间(s)
从内存情况,来看,S0、伊甸园已经被打满,old已经被打满,排除了是大对象实例过多直接把old打满的情况,继续分析
查看应用启动的jvm参数
-Xms2g -Xmx2g -Xmn1g -Xss1024K -XX:PermSize=256m -XX:MaxPermSize=512m -XX:ParallelGCThreads=8 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+UseCMSCompactAtFullCollection -XX:SurvivorRatio=4 -XX:MaxTenuringThreshold=10 -XX:CMSInitiatingOccupancyFraction=80
说两个参数的含义吧
XX:SurvivorRatio=4,这个参数的意思是Survivor两个区与新生代的比例,设置为4的意思是两个区与新生代的比例为2:4,MaxTenuringThreshold=10, 这个参数的意思是对象标记多少次后记为old对象,放入到老年代中,设置为10就是新生代对象被标记10次还没有释放,就放到老年代中,从参数上看,造成old区过高报警的原因是有的对象在新生代中,被标记了10次都没有被释放,被放入到了老年代中,造成了老年代过大,FGC频率过高
经朋友指点,这一块的分析有问题,有问题的分析留着,再贴一下朋友的分析,对比一下
动态对象年龄判定:为了能更好地适应不同程度的内存状况,虚拟机并不是永远地要求对象的年龄必须达到了MaxTenuringThreshold才能晋升到老年代,如果在Survivor空间中相同年龄的所有对象大小的总和大于Survivor空间的一半,年龄大于或等于年龄的对象就可以直接进入老年代,无须等到MaxTenuringThreshold中要求的年龄
朋友的指导
导出dump文件,使用jvisualvm.exe查看
导出dump文件的过程就不赘述了,简单贴一下命令
jmap -dump:format=b,file=serviceDump.dat pid
jvisualvm是一个jdk自带的内存分析工具,一般位置在jdk安装目录下:
C:\Program Files\Java\jdk1.8.0_141\bin\jvisualvm.exe
jvisualvm工具界面
在这选择已经导出的dump文件,查看内存中类的实例数、实例大小
发现是Char[],String,HashMap这三个的实例是jvm中最多的,实例数分别占31%、30.9%、30.2%,总共占了92.1%,实例的大小分别占35.8%、14.6%、22.4%,总共占了72.8%,主要是这三个类的实例占用过大的内存
查看Char[]的实例信息
点击去,查看Char[]的实例信息,从大到小的排列
查看最大的这些实例,发现这些实例里面的内容是
<graph lineThickness='3' showValues='0' formatNumberScale='1' anchorRadius='3' divLineAlpha='20' divLineColor='CC3300' divLineIsDashed='1' showAlternateHGridColor='1' alternateHGridAlpha='5' alternateHGridColor='CC3300' shaowAlpha='40d' chartRightMargin='3..
目测这些都是前端使用的图表所用到的数据,设计不合理,这些图表的html代码由后台代码给前端返回了
实例里面的内容
查看这些实例的堆栈信息
查看这些实例的垃圾回收根节点
发现是根节点是 StringBuilder对象,查看堆栈信息
堆栈信息
通过堆栈信息,就定位到了代码中,分析代码,原因基本是,原来的设计方案有问题,给前端返回的数据里面包含了大量的html代码,从存储中拿数据的过程、拼接数据的过程过于漫长了,造成了大量对象的生命周期过长,对象被 标记到了old中,造成了old区过高,这里就是是分享下,排查的过程,不对原因过于详细的表述了
来源:https://www.jianshu.com/p/f04c04ed462f


猜你喜欢
- 前言面对众多卡片层叠效果,我们的产品童鞋也突发奇想,搞出了另一种卡片层叠切换展示的交互,而且产品狗们居然要求多做几种动效给他们看,好让他们选
- 导入后gradle building 一直到跑,卡住了,一般是gradle没有下载,又下不下来的原因。去 http://serv
- 前言今天刷个题,遇到一个很有趣的问题,关于Comparator的使用,感觉也是一个关于写代码的一些小细节的问题关于ComparatorCom
- @GetMapping和@GetMapping(value=““)区别背景初期对于@GetMappi
- 实现客户端发送请求,服务器端响应机制UDP客户端代码using System;using System.Text;using System.
- SSL是为网络通信提供安全以及保证数据完整性的的一种安全协议,SSL在网络传输层对网络连接进行加密。例:cas 的单点登陆就用到了SSL一、
- 本文实例为大家分享了Unity实现俄罗斯方块第一部分,供大家参考,具体内容如下准备工作1、新建一个2D项目,新建成功以后设置相机的一些参数2
- C#一些延时函数sleep延时方法System.Threading.Thread.Sleep(1000); //毫秒实现的是非独占性延时函数
- /** * 进行BigDecimal对象的加减乘除,四舍五入等运算的工具类 * * @author Marydon * @createTi
- JDK、JRE、JVMJDK包含JRE,而JRE包含JVMJDK(Java Development Kit)是针对Java开发员的产品,是整
- 用户关闭软件时,软件一般会给“是否确认关闭”的提示。通常,我们把它写在FormClosing 事件中,如果确定关闭,就关闭;否则把FormC
- 一、前言文稿扫描大家用的都比较频繁、想是各种证件、文件都可以通过扫描文稿功能保存到手机。相比直接拍照,在扫描文稿时,程序会对图像进行一些矫正
- 本文实例讲述了基于C++实现的哈夫曼编码解码操作。分享给大家供大家参考,具体如下:哈夫曼编码是一个通过哈夫曼树进行的一种编码,一般情况下,以
- 概念介绍什么是死信死信可以理解成没有被正常消费的消息,在RabbitMQ中以下几种情况会被认定为死信:消费者使用basic.reject或b
- 本文实例讲述了java统计字符串中重复字符出现次数的方法。分享给大家供大家参考,具体如下:package com;import org.ju
- 1. 定义在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。2. 使用的
- 看书的时候被一段代码能凌乱啦,代码是这样的:package 继承;abstract class People {
- AbstractQueuedSynchronizerAbstractQueuedSynchronizer 简称 AQS ,抽象队列同步器,用
- 1.@RequestMapping注解1.1@RequestMapping注解的功能从注解名称上我们可以看到,@RequestMapping
- 很多人的程序在本地运行是好的,但是发布在服务器上后就会有各种各样的问题,但是服务器上又不能直接调试,所以直接读写本地日志成为解决问题的关键,