Java 应用堆外内存泄露问题排查 | 京东云技术团队
问题是怎么发现的
最近有个 java 应用在做压力测试
压测环境配置:
CentOS 系统 4 核 CPU 8g 内存 jdk1.6.0_25,jvm 配置-server -Xms2048m -Xmx2048m
出现问题如下
执行 300 并发,压测持续 1 个小时后内存使用率从 20%上升到 100%,tps 从 1100 多降低到 600 多。
排查问题的详细过程
首先使用 top 命令查看内存占用如下
然后查看 java 堆内存分布情况,查看堆内存占用正常,jvm 垃圾回收也没有异常。
然后想到了是堆外内存泄漏,由于系统中用的 jsf 接口比较多,底层都是依赖的 netty。
首先考虑的是 java 中 nio 包下的 DirectByteBuffer,可以直接分配堆外内存,不过该类分配的内存也有大小限制的,可以直接通过-XX:MaxDirectMemorySize=1g 进行指定,并且内存不够用的时候代码中会显式的调用 System.gc()方法来触发 FullGC,如果内存还是不够用就会抛出内存溢出的异常。
为了验证这一想法,于是在启动参数中通过-XX:MaxDirectMemorySize=1g 指定了堆外内存大小为 1g,然后再次进行压测,发现内存还是在持续增长,然后超过了堆内存 2g 和堆外内存 1g 的总和,并且也没有发现有内存溢出的异常,也没有频繁的进行 FullGC。所以可能不是 nio 的 DirectByteBuffer 占用的堆外内存。
为了分析堆外内存到底是谁占用了,不得不安装 google-perftools 工具进行分析。它的原理是在 java 应用程序运行时,当调用malloc时换用它的libtcmalloc.so,这样就能做一些统计了。
安装步骤如下:
下载 http://download.savannah.gnu.org/releases/libunwind/libunwind-0.99-beta.tar.gz,
./configure
make
sudo make install //需要 root 权限
下载 http://google-perftools.googlecode.com/files/google-perftools-1.8.1.tar.gz,
./configure --prefix=/home/admin/tools/perftools --enable-frame-pointers
make
sudo make install //需要 root 权限
修改 lc_config: sudo vi /etc/ld.so.conf.d/usr-local_lib.conf,加入/usr/local/lib(libunwind 的 lib 所在目录)
执行 sudo /sbin/ldconfig,使 libunwind 生效
在应用程序启动前加入:
export LD_PRELOAD=/home/admin/tools/perftools/lib/libtcmalloc.so
export HEAPPROFILE=/home/admin/heap/gzip
启动应用程序,此时会在/home/admin/heap 下看到诸如 gzip_pid.xxxx.heap 的 heap 文件
使用/home/admin/tools/perftools/bin/pprof --text $JAVA_HOME/bin/java test_pid.xxxx.heap 来查看
/home/admin/tools/perftools/bin/pprof --text $JAVA_HOME/bin/java gzip_22366.0005.heap > gzip-0005.txt
然后查看分析结果如下
可以看到是 Java_java_util_zip_Inflater_init 这个函数一直在进行内存分配,查看 java 源码原来是
如何解决问题
1、升级 jdk 版本为 jdk7u71 ,压测一段时间后,发现内存增长有所减慢,并且会稳定在一定的范围内,不会把服务器的所有内存耗尽。猜测可能是 jdk1.6 版本的 bug
2、尽量不要使用 jimdb 客户端的 getObject 和 setObject 方法,如果真的需要保存对象,可以自己实现序列化和反序列化,不要解压缩功能,因为对象本来就不大,压缩不了多少空间。如真的需要解压缩功能,最好设置解压缩阀值,当对象大小超过阀值之后在进行解压缩处理,不要将所有对象都进行解压缩处理。
作者:京东零售 曹志飞
来源:京东云开发者社区
版权声明: 本文为 InfoQ 作者【京东科技开发者】的原创文章。
原文链接:【http://xie.infoq.cn/article/43fa5218648736e9b3c091f3e】。文章转载请联系作者。
评论