为什么老年代内存在一直上升?

最近看到 Grafana 监控大屏中,负责的一个服务的两个节点中, Old Generation 内存都再稳步上升,并且并未触发 Major GC,此时好奇心起,到底是应用中的哪些操作产生了这样的影响呢?

随后我联系运维同事,帮忙导出 dump 文件,选择了 Pod 1执行命令 jmap -<img src="dump" alt="" width="50%" />:live,format=b,file=heap001

Pod 1 执行的 dump 命令后,Old Gen 内存走势如图:

可以看到,此次 dump 引发了一次 Major GC(Heap Dump Initlated),Old Gen 内存迅速被释放,因此可以推断出,此服务实例之前的老年代存在大量垃圾对象,因为未触发 Major GC,导致这些对象一直占用内存未被及时清除。

那到底是哪些对象一直源源不断地进入老年代呢?

Pod 2 和 Pod 1 的资源配置情一致,并且 Old Gen 内存走势也大致相同,随后让运维同事在 Pod 2 执行 dump 命令: jmap -dump:format=b,file=heap002 , 除了生成的文件名称和 Pod 1 不一样外,火眼金睛的你应该也已经发现,此次命令少了个可选参数 live ,这样生成内存快照前并不会触发 Full GC,利于我们观察垃圾对象的情况。

利用 IDEA 的一款插件 Profiler 分析下 heap dump 文件。

观察 Class Tab 页,根据 Shallow 从大到小排列(Shalllow 表示这个对象占用堆的大小,Retained 表示下一次 Major GC 后对象在堆中的大小)。和业务代码直接相关的两个类 ApplicationBankRegionTree ,可以明显的看到,这两个类的实例存在近 140M 的垃圾对象未被回收。那么这下可以精确地找到相关类,从而顺藤摸瓜找到关键业务代码:

RegionTree 同样也有对应的缓存。看到这些代码,想必结论也清楚了:每隔 30 min 刷新一遍 LocalCache 缓存,这些缓存实例也算是长期存活的对象了,它们或因年龄到达准入年龄(默认15岁),或因动态年龄判定机制,或因空间分配担保机制进入老年代也是正常现象。

至此,Old Gen 内存缓慢上升的原因,已显露水面,JVM 内存中存在一些长期存活的缓存对象在内存中,并且这些缓存对象每隔一段时间都会重新生成新的实例,随着应用运行的时间越来越长,转入老年代的业务缓存实例也越来越多,最终就会呈现出 Old Gen 内存上升的现象。

那么这样的现象会对应用产生什么影响吗?从目前应用运行的状态来看,即使内存缓慢增长也未触发 Major GC,说明这些缓存对象集合实例并不大,即使经过很长一段时间,达到了 Old Gen 内存限制,那么就会发生 Major GC 来清理这些垃圾,这也是正常现象。而目前此应用发生的 Major GC 次数非常少。所以此应用的内存情况是正常的。

判断应用内存情况,我们可以从应用的 Heap 内存使用大小、 Heap 内存是否可通过 GC 释放掉、 GC 频率以及耗时情况等方面入手。当发现有内存问题时,可使用 jmap 命令获取 JVM 内存快照,并配合一些 dump 分析工具(Profiler、Yourkit(Paid))对内存进行深入分析,找到问题所在。

Reference

相关推荐
YuTaoShao1 小时前
【LeetCode 热题 100】139. 单词拆分——(解法一)记忆化搜索
java·算法·leetcode·职场和发展
Best_Liu~2 小时前
策略模式 vs 适配器模式
java·spring boot·适配器模式·策略模式
你的人类朋友2 小时前
【Node&Vue】什么是ECMAScript?
前端·javascript·后端
direction__2 小时前
Java Main无法初始化主类的原因与解决方法(VsCode工具)
java·vscode
帧栈2 小时前
开发避坑指南(29):微信昵称特殊字符存储异常修复方案
java·mysql
每天的每一天2 小时前
面试可能问到的问题思考-Redis
java
青云交3 小时前
Java 大视界 -- Java 大数据在智能安防人脸识别系统中的活体检测与防伪技术应用
java·大数据·生成对抗网络·人脸识别·智能安防·防伪技术·活体测试
你的人类朋友3 小时前
说说你对go的认识
后端·云原生·go
学习至死qaq3 小时前
信创产品TongLinkQ安装及springboot2整合使用
java·东方通·tonglinkq
我崽不熬夜3 小时前
Java中基本的输入输出(I/O)操作:你知道如何处理文件吗?
java·后端·java ee