一次老生代内存使用占比飙升问题解决
一次老生代内存使用占比飙升问题解决
老生代内存使用占比图示
如图所示老生代内存占比不断增加,超过80%系统自动报警,之前的解决方案是手动重启😜。
1、保存现场
为了解决上面老生代问题,首先需要dump下堆文件
命令:
ps -ef|grep DialingRobot
DialingRobot是服务名称,找到对应的pid
pid:70992
dump堆内存
jmap -dump:format=b,file=1.dump 70992
将堆内存dump下来
为了分析内存的变化,可以在不同的时间进行dump操作,可以分析前后的内存变化,更方便查找问题
2、分析问题
1、jprofiler分析dump文件
将文件重命名为20200520.hprof(.hprof是可以分析的堆文件)
打开后长这样
可以去看一下biggest对象
点开之后发现,占有内存比较大是正常的,这些类里面都存放着大量的内存缓存。
第二考虑是不是这个类太多了,没有释放,分析两个时间段的堆内存,两个dump中的这个对象的数量大小差异不大。尝试mat去分析下dump文件。
2、mat分析dump文件
主要使用两个模块:Histogram和LeakSuspects
Histogram主要展示堆内的各个对象的大小
将两个hprof文件导入mat,可以使用比较去分析两个内存的前后的变化
两个hprof文件前后对象的差异、内存的差异
分析这些差异,没有看到什么有用的信息。
尝试使用第二个mat的工具:Leak Suspects
mat给出两个suspect,可以分析下,第一个还是之前的class文件过大,但是是由于内部维护了一部分缓存造成的,第二个cs csSocket也不是,跟JProfiler差异不大。
这个时候分析到达一个比较艰难的时候。
这个时候查看下jvm的参数设置:
可以看出来整个堆的大小是:1g,新生代是256mb,老年代是1024-256=768mb,看上去没有什么问题。
这个时候需要分析我们的应用,我们的应用中的对象的特征,我们应用中的对象很少有需要一直存在的对象,更多是朝生夕死的对象,这样的话,这个的是不是有问题呢?
我们去看看新生代的内存、回收情况。
可以看出来,老生代内存使用率的增加和新生代的gc强相关,新生代gc一次,老生代的内存使用率升高一点
3、解决问题
修改jvm参数
将堆内存从1g->2g,新生代256m->1024m,观察老生代情况。
可以看出来:老生代内存使用占比稳定,新生代回收频率也降低了很多(13 -> 3 /30min),单次耗时:(10ms -> 20ms),30分钟内gc时间从130ms -> 60ms,降低了一倍
由此可见,服务中存在大量短期临时对象,扩容新生代空间后,Minor GC频率降低,对象在新生代得到充分回收,只有生命周期长的对象才进入老年代。这样老年代增速变慢,Major GC频率自然也会降低。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器