一次疑似 JVM native 内存泄漏的排查实录

最近开发同学反馈,某定时任务服务疑似有内存泄漏,整个进程的内存占用比 Xmx 内存大不少,而且看起来是缓慢上升的,做了下面这次分析,包括下面的内容:

  • 分析 JVM native 内存的一些常见思路
  • 内存增长了,怎么甄别是不是内存泄漏
  • 一个完全不熟悉的项目如何找到可能导致 native 内存分配的代码
  • 经典的 Linux 64M 内存问题
  • 到底是内存碎片还是内存泄漏

现象

这个定时任务的应用设置 Xmx 为 925M,但是 native 内存缓存持续增长,但是增长到一定阶段也会保持稳定,不再继续增长。

是内存泄漏吗?

不管是不是内存泄漏,首先要搞清楚的是这段增长的内存是什么,土方法就是用 pmap -x 持续观察内存地址空间的变化。

经过几个小时的 pmap 后台运行,很快发现堆内存几乎无变化,增长的区域都在 64M 内存空间,这就是经典的 glibc 内存分配 64M 问题。

关于 Linux 64M 内存问题,我之前写过几篇相关的文章,大家感兴趣可以去看。

从这里基本可以确定是 native 带来的问题,接下来就是 dump 出来看里面到底存了什么。这里有几个方法

  • 使用 gdb
  • 写一个脚本读取 /proc/<pid>/mem
  • 我自己用 Go 写的一个小工具(可能过段时间释放出来)

脚本内容如下:

cat /proc/$1/maps | grep -Fv ".so" | grep " 0 " | awk '{print $1}' | grep $2 | ( IFS="-"
while read a b; do
dd if=/proc/$1/mem bs=$( getconf PAGESIZE ) iflag=skip_bytes,count_bytes \
skip=$(( 0x$a )) count=$(( 0x$b - 0x$a )) of="$1_mem_$a.bin"
done )

执行这个脚本,传入进程号和起始地址就可以把对应内存 dump 到文件中。接下来可以通过 strings 初步查看文件里面有没有认识的字符串。通过 strings 发现很多 jar 包文件里的内容,部分内容如下:

这个内容是项目依赖 jar 包 HikariCP-2.5.1.jar 的 MANIFEST.MF 文件的内容

.
├── M
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值