情景:今天测试环境发现应用出现内存溢出的问题。这是从来没有出现过的问题,在关闭此次版本新上线的功能后仍发现Perm区的内存持续在增长。
jdk版本:1.7
环境:linux
======================================================
起因:测试环境出现内存溢出
排查过程:
1,重现此内存溢出问题
查看应用日志,定位到哪一个操作导致内存溢出。发现是在调用接口之后出现。但由于测试环境有测试人员不断在部署版本,所以重启应用,再调用接口,发现无异常,于是使用JMeter多次请求接口,重现异常。
2,关闭此次版本功能
此次版本新上线的功能逐一关闭开关,定位是否是由新功能引起,发现关闭所有新功能开关后问题仍然存在
3,期间使用jdk自带工具分析应用状况与gc日志
<a>ps -ef | grep java 查看应用
<b>jstat -gcutil pid 1000 持续观察应用情况
<c>jmap -dump 把内存情况拷贝下来
<d>无gc日志
发现应用的启动脚本设置的启动参数有问题,于是重新设置启动参数与gc日志
重设的启动参数包括-Xmx,-Xms,-XX:PermSize,-XX:MaxPermSize和增加GC日志,垃圾回收器等
4,重设参数后,启动应用
继续使用jdk工具命令观察,发现Perm区一直在增长,FGC后也是一直增长,但是没有内存溢出
5,此期间怀疑有类在不断加载,或者缓存在不断增大
6,排查代码,发现不是缓存原因,很大可能是类在不断增加,但是这个就很奇异了
7,在开发环境重新部署应用,发现与测试环境的现象相同,于是又在开发环境重新部署上一个版本的应用,彻底排除是新增功能引起的问题,使用jdk自带工具观察,发现Perm区仍有增长
除了之前的工具,还使用jconsole连接应用,观察应用的情况
8,再次排查代码,并且使用两种方法测试
<a>,for循环10W次请求开发环境应用,观察应用的Perm区
<b>,测试应用,手动点击发送请求,请求开发环境应用
<c>,排查应用代码
=================================
结果:
在上一个版本中仍存在Perm区不断增长的问题,其实原因是代码中一直有classloader在作怪,无法释放类,并且在不断加载,只是从未被发现,此次是由于启动脚本缺失某些参数才暴露出的问题。所以需要去除相对应的代码
临时解决方案:
由于版本问题,无法修改代码,而Perm区的增长,到一定值之后,增长速度会非常缓慢,所以暂时决定先调整启动脚本,增大Perm区的大小,支撑到下一个版本修改代码
原文地址:https://www.cnblogs.com/huangtao1927/p/jvm.html