问题分析
内存泄漏是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory(OOM)那就是内存溢出。内存溢出也就是内存不够用,在测试环境没有大量用户请求的场景下基本上很难出现oom,大部分应用都是上线生产环境遇到内存溢出,java.lang.OutOfMemoryError:Java heap space问题。
问题发生
应用内存溢出,服务器基本宕机,对业务造成较大影响,从日志定位到内存泄漏很容易,但如何定位到是哪里代码造成内存泄漏,看完本篇文章相信你会有一个比较清晰的思路。
查看日志发现堆内存泄漏
java.lang.OutOfMemoryError: Java heap space
21-02-02 10:11:04.693 [DiscoveryClient-0] WARN com.netflix.discovery.TimedSupervisorTask.run - task supervisor timed out
主业务服务占用服务器2.9g内存
[root@szvmapstms01 ~]# top -b -n 1 | grep java| awk '{print "PID:"$1",mem:"$6",CPU percent:"$9"%","mem percent:"$10"%"}'
PID:52898,mem:433604,CPU percent:6.2% mem percent:5.4%
PID:52957,mem:351160,CPU percent:6.2% mem percent:4.4%
PID:15446,mem:2.9g,CPU percent:0.0% mem percent:37.7%
PID:52936,mem:534252,CPU percent:0.0% mem percent:6.7%
进入JDK的bin目录执行
./jmap -dump:format=b,file=/srv/jvmDmp.hprof 43360
参数说明 (1)file:生成dump文件的路径及文件名称 (2)43360应用的PID
查看supervisor发现启动分配堆内存2g
[program:服务名]
command=java -jar -Dserver.port=9633-Xms512m -Xmx2048m -Xss256K -XX:MetaspaceSize=200m -XX:MaxMetaspaceSize=256m -XX:+UseParNewGC -XX:+UseConcMarkSweepGC 服务名.jar --spring.config.location=/config/application-recall.yml
修改启动参数内存泄漏时生成内存dump
[program:服务名]
command=java -jar -Dserver.port=9633-Xms512m -Xmx2048m -Xss256K -XX:MetaspaceSize=200m -XX:MaxMetaspaceSize=256m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/srv/jvmDump -XX:+UseParNewGC -XX:+UseConcMarkSweepGC 服务名.jar --spring.config.location=/config/application.yml
参数说明
(1)-XX:+HeapDumpOnOutOfMemoryError参数表示当JVM发生OOM时,自动生成DUMP文件。
(2)-XX:HeapDumpPath=${目录}参数表示生成DUMP文件的路径及文件名称。
从服务器拿下来dump文件
下载分析工具(博主这里使用的JProfiler)
1.查看class
2.查看biggest object
3.Use Slected Objects
4.Incoming references
incoming references-显示这个对象被谁引用
outcoming references-显示这个对象引用的其他对象5.查看
ok以上已经定位到代码具体位置
查看代码
结合业务分析代码
业务场景需要分段抓取大量页面元素,开发同事把大量页面元素放入redis,该方法主要用于一次性读取出来,设计方案不合理,内存消耗过高导致OOM。