某游戏海外版本堆外内存泄露排查
-
现象
- 线上有部分服务器用top发现Java进程内存占用占比达到99,而且出现了有一个服务器被Linux OOM Kill
-
排查
- 选择了110服,该机器的Java进程最大堆内存设置的是9710m,但是进程占用的RES却达到了14g,远比堆内存大很多,所以初步确认,一定是出现了堆外内存泄露
-
工具安装
-
堆外内存泄露的工具通常是gperftools
-
同时要安装libunwind
1. libunwind默认安装在/usr/local/lib 2. 需要root在/etc/ld.so.conf.d建一个usr_local_lib.conf,文件内容是/usr/local/lib/ 3. 然后使用ldconfig命令刷一下
-
java进程启动脚本增加参数
export LD_PRELOAD=/usr/local/lib/libtcmalloc.so export HEAPPROFILE=/tmp/nonheapleak
-
注:
- 第一次启动的时候jvm直接crash了,crash日志显示是因为libunwind这个库
- 重新安装了一个新版本的libunwind
- 类似issues SIGSEGV JVM exits stating libunwind.so as the problematic frame
-
-
定位
-
启动后,在/tmp目录会每隔一段时间都会生成如nonheapleak_31733.0088.heap、nonheapleak_31733.0089.heap等文件
-
使用如下命令分析
$ pprof --text ~/kof/usr/jdk/bin/java nonheapleak_31733.0089.heap | less
-
输出
Using local file /opt/home/service/kof/usr/jdk/bin/java. Using local file nonheapleak_31733.0089.heap. Total: 1509.3 MB 1293.1 85.7% 85.7% 1293.1 85.7% luaM_realloc_ 179.4 11.9% 97.6% 179.4 11.9% os::malloc 30.0 2.0% 99.5% 30.0 2.0% init 2.4 0.2% 99.7% 2.4 0.2% updatewindow 1.2 0.1% 99.8% 1.2 0.1% strbuf_resize 1.2 0.1% 99.9% 1.2 0.1% ObjectSynchronizer::omAlloc 1.0 0.1% 99.9% 1.0 0.1% inflateInit2_
-
从上面可以看到luaM_realloc_占用了较大内存,初步判断堆外内存占用这块主要是lua
-
所以下面的排查和解决思路是
为什么lua占用了这么大的内存
是否有泄露的可能
需要客户端同学一起排查,一个gc后的luastate到底内存都有哪些对象
是否关闭本地复盘,因为有潜在的oom-kill的风险
-
-
其他
- -XX:MaxDirectMemorySize=size用于设置New I/O(
java.nio
) direct-buffer allocations的最大大小,即这个主要是nio相关,即狭义的‘堆外内存’。而Direct ByteBuffer分配出去的直接内存其实也是由GC负责回收的 - 而本例是指jni分配的内存导致的内存泄露,这个是无法被jvm回收的
- -XX:MaxDirectMemorySize=size用于设置New I/O(
-
ref
网友评论