最近工作中碰到了内存泄漏的问题
emmm, 这曲线还真挺恐怖的。
分析&解决过程:
一、 为啥没有fullGC
ps -ef 看了下虚拟机参数,发现堆空间就开了8g,这曲线都涨到14g了,问了下同事,曲线显示的是进程内存(堆内内存+堆外内存),所以下面就分别看下堆内内存和堆外内存的情况了。
二、 堆内内存的情况
1. 先理解下内存模型
内存模型
// https://mp.weixin.qq.com/s/uajRpzDayZSwTEPhFUoVbQ
新 new 的对象放在 Eden 区,当 Eden 区满之后进行一次 MinorGC,并将存活的对象放入 S0(survivor0);
当下一次 Eden 区满的时候,再次进行 MinorGC,并将存活的对象和 S0 的对象放入S1(S0 和 S1 始终有一个是空的);
依次循环直到 S0 或者 S1 快满的时候将对象放入 old 区,依次,直到 old 区满进行 FullGC。
jdk1.7 之前 Java 类信息、常量池、静态变量存储在 Perm 永久代,类的原数据和静态变量在类加载的时候放入 Perm 区,类卸载的时候清理;在 1.8 中,MetaSpace 代替 Perm 区,使用本地内存,常量池和静态变量放入堆区,一定程度上解决了在运行时生成或加载大量类造成的 FullGC,如反射、代理、groovy 等。
2. jmap
这是堆的配置信息了
这是堆的使用情况(堆申请了8g,只用了1g多)
3. jstat 每隔1s看下堆内不同区的动态情况
也没啥毛病
三、 堆外内存分析
1. 通过对堆内内存的分析,内存泄露的锅就和堆内内存没关了,所以很多查内存泄漏的blog说的dump、JProfile、gc日志分析工具等等的就免了
2. 使用google的gperftools进行堆外内存的分析
参考:
https://qsli.github.io/2017/12/02/google-perf-tools/
(1) 安装&配置
---~/.bashrc 中配置环境变量
export LD_PRELOAD=/home/work/soft/gperftools-2.5/lib/libtcmalloc.so
export HEAPPROFILE=/data/soft/logs/tmp1/ -- 貌似这里得加个1
export HEAP_PROFILE_ALLOCATION_INTERVAL=2000000000
----- 缺省是1G
--------------------------------分割线------------------------------
# if configuration files exist, prepend their contents to $@ so it can be processed by this runner
[[ -f "$script_conf_file" ]] && set -- $(loadConfigFile "$script_conf_file") "$@"
export LD_PRELOAD=/home/work/soft/gperftools-2.5/lib/libtcmalloc.so
export HEAPPROFILE=/data/soft/logs/tmp/
run "$@"
$ vi baike-answer
--------------------------------分割线------------------------------
god restart -- 重启服务
(2) 查看服务生成文件
环境变量配置的路径中
ls -ltra -- 注意是隐藏文件
-rw-r--r-- 1 work work 1048571 Feb 5 16:44 .0738.heap
-rw-r--r-- 1 work work 1048567 Feb 5 16:46 .0739.heap
-rw-r--r-- 1 work work 1048561 Feb 5 16:47 .0740.heap
-rw-r--r-- 1 work work 1048565 Feb 5 16:49 .0741.heap
-rw-r--r-- 1 work work 1048565 Feb 5 16:51 .0742.heap
-rw-r--r-- 1 work work 1048565 Feb 5 16:52 .0743.heap
-rw-r--r-- 1 work work 1048569 Feb 5 16:54 .0744.heap
-rw-r--r-- 1 work work 1048574 Feb 5 16:55 .0745.heap
(3) 导出成pdf文件
/home/work/soft/gperftools-2.5/bin/pprof --pdf ~/java/bin/java ./.0748.heap > result.pdf
(4) 查看pdf文件
对比分析上述结果,可以看到Java_org_tensorflow_TensorFlow_libraryOpList使用的内存持续增长,这个地方存在(堆外)内存泄漏(其他对象使用内存变化不大)
那么接下来应该分析服务中tensorflow的使用情况
四、 解决问题
todo:
五、 总结
要分清是堆内内存泄露还是堆外内存泄露