记一次JVM内存泄漏问题排查、分析过程

背景

项目使用框架为springboot + akka(想要了解akka框架的同学可自行查看),JDK版本1.8 使用的垃圾回收器为1.8默认的UseParallelGC

工具说明

  1. 压测工具使用的是jmeter脚本
  2. 性能监测工具使用的是jdk自带工具,jconsole、jvisualvm,一般第一个基本可以满足监测需求
    在这里插入图片描述
  3. 分析工具使用的是IBM的工具,ha450.jar(分析dump文件)、jca450.jar(分析线程信息)
    分析dump文件也可以使用 JProfile和mat(两个都为可视化分析工具)

使用相关命令说明

  1. 获取dump文件命令
    (1) 自己手动获取使用命令 jmap -dump:format=b,file=dump18947_1.hprof 18947,pid替换为自己服务pid即可。
    (2) 在服务启动命令添加jvm参数 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/dev/jvm_log,在服务发生内存泄漏时会自动生成dump文件在指定目录下。
  2. 获取线程信息命令
    使用 jstack 命令获取,如 jstack pid > jstack.log

内存泄漏分析过程

  1. 首次压测 设置堆大小为2G,压测几个小时发现服务出现 java.lang.OutOfMemoryError: GC overhead limit exceeded 异常,首次认为是堆内存设置太小(压测服务本身比较吃资源所以有此猜测,是否因为参数问题要视项目具体情况而言),然后重新设置堆大小为 8G后重新压测,发现老年堆持续上涨且GC后并不能释放,所以定位为代码问题。
    在这里插入图片描述
  2. 因要在本地分析,dump文件较大时使用分析工具无法打开,所以重新设置堆大小为2G重新进行压测。使用jmap命令分别在压测开始的10min、1h、内存溢出时获取dump文件进行对比分析,这样能够很直观的看出来哪些资源快速增长且未释放。
  3. 这里我使用的分析工具为 ha450.jar和mat,下面使用mat进行说明
    在这里插入图片描述
    在这里插入图片描述
    这里的可视化工具会把问题给暴露出来,dump两个文件对比可以明显的发现是akka 流使用时候的问题,具体情况还需要再次进行分析。
  4. 查看具体问题
    在这里插入图片描述
    这里可以给我们更详细的信息,当我们选择点击进去查看时可以发现问题
    在这里插入图片描述
    这时候我们去自己的代码中去追溯,可以发现一些对象没有释放,一直被占用。
  5. 问题处理
    有时候内存泄漏点可能不止一个,这个需要我们多次压测并进行分析,我这里只是讲分析的一个思路。我在压测的过程中就是发现了多个泄漏点,逐一解决后压测内存才恢复正常。
    出现内存泄漏的原因有很多,如:
    (1) 对象创建较多且一直被引用导致gc不能回收
    (2) 创建线程过多导致的内存溢出
    (3) 一些监听器的使用
    (4) 静态集合类引起的内存泄漏等

在解决这类问题的时候,我们可以先找到有问题的代码进行修改,然后对一些强引用对象可以尝试手动置空释放。如果使用线程池要正确的去使用,并对一些资源进行回收释放。

共勉~

新增:

  1. dump当前进程文件命令:jmap -dump:format=b,file=文件名称.hprof 进程号;
  2. jmeter启动命令: nohup ./apache-jmeter-4.0/bin/jmeter.sh -n -t test.jmx -l result.jtl &
  3. jar启动参数:nohup java -Xmx8g -Xms8g -XX:+UnlockExperimentalVMOptions -Dfile.encoding=UTF-8 -XX:+UseG1GC -XX:MaxGCPauseMillis=10 -XX:GCPauseIntervalMillis=200 -XX:+UseStringDeduplication -XX:+ParallelRefProcEnabled -XX:+DisableExplicitGC -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/dev/jvm_log -Djava.rmi.server.hostname=172.31.184.209 -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=10099 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -jar service-3.1-SNAPSHOT.jar &
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值