【发布时间】:2016-11-04 08:04:11
【问题描述】:
我们有一个在 Mule 上运行的 java 应用程序。我们将 XMX 值配置为 6144M,但经常看到整体内存使用量不断攀升。前几天我们主动重新启动它之前,它已经接近 20 GB。
Thu Jun 30 03:05:57 CDT 2016
top - 03:05:58 up 149 days, 6:19, 0 users, load average: 0.04, 0.04, 0.00
Tasks: 164 total, 1 running, 163 sleeping, 0 stopped, 0 zombie
Cpu(s): 4.2%us, 1.7%sy, 0.0%ni, 93.9%id, 0.2%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 24600552k total, 21654876k used, 2945676k free, 440828k buffers
Swap: 2097144k total, 84256k used, 2012888k free, 1047316k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
3840 myuser 20 0 23.9g 18g 53m S 0.0 79.9 375:30.02 java
jps命令显示:
10671 Jps
3840 MuleContainerBootstrap
jstat 命令显示:
S0C S1C S0U S1U EC EU OC OU PC PU YGC YGCT FGC FGCT GCT
37376.0 36864.0 16160.0 0.0 2022912.0 1941418.4 4194304.0 445432.2 78336.0 66776.7 232 7.044 17 17.403 24.447
启动参数是(敏感位已更改):
3840 MuleContainerBootstrap -Dmule.home=/mule -Dmule.base=/mule -Djava.net.preferIPv4Stack=TRUE -XX:MaxPermSize=256m -Djava.endorsed.dirs=/mule/lib/endorsed -XX:+HeapDumpOnOutOfMemoryError -Dmyapp.lib.path=/datalake/app/ext_lib/ -DTARGET_ENV=prod -Djava.library.path=/opt/mapr/lib -DksPass=mypass -DsecretKey=aeskey -DencryptMode=AES -Dkeystore=/mule/myStore -DkeystoreInstance=JCEKS -Djava.security.auth.login.config=/opt/mapr/conf/mapr.login.conf -Dmule.mmc.bind.port=1521 -Xms6144m -Xmx6144m -Djava.library.path=%LD_LIBRARY_PATH%:/mule/lib/boot -Dwrapper.key=a_guid -Dwrapper.port=32000 -Dwrapper.jvm.port.min=31000 -Dwrapper.jvm.port.max=31999 -Dwrapper.disable_console_input=TRUE -Dwrapper.pid=10744 -Dwrapper.version=3.5.19-st -Dwrapper.native_library=wrapper -Dwrapper.arch=x86 -Dwrapper.service=TRUE -Dwrapper.cpu.timeout=10 -Dwrapper.jvmid=1 -Dwrapper.lang.domain=wrapper -Dwrapper.lang.folder=../lang
将 jps 的“容量”项加起来表明只有我的 6144m 用于 java 堆。其余的内存在哪里使用?堆栈内存?本机堆?我什至不知道如何继续。
如果继续增长,它将消耗系统上的所有内存,我们最终会看到系统冻结并抛出交换空间错误。
我有另一个进程正在开始增长。目前大约 11g 常驻内存。
pmap 10746 > pmap_10746.txt
cat pmap_10746.txt | grep anon | cut -c18-25 | sort -h | uniq -c | sort -rn | less
Top 10 entries by count:
119 12K
112 1016K
56 4K
38 131072K
20 65532K
15 131068K
14 65536K
10 132K
8 65404K
7 128K
Top 10 entries by allocation size:
1 6291456K
1 205816K
1 155648K
38 131072K
15 131068K
1 108772K
1 71680K
14 65536K
20 65532K
1 65512K
And top 10 by total size:
Count Size Aggregate
1 6291456K 6291456K
38 131072K 4980736K
15 131068K 1966020K
20 65532K 1310640K
14 65536K 917504K
8 65404K 523232K
1 205816K 205816K
1 155648K 155648K
112 1016K 113792K
这似乎在告诉我,因为 Xmx 和 Xms 设置为相同的值,所以 Java 堆的单个分配为 6291456K。其他分配不是 java 堆内存。这些是什么?它们被分配到相当大的块中。
【问题讨论】:
-
不是一个正确的答案,但我在网络缓冲区中遇到过这种情况。显然,如果您订阅多播并且不阅读它(或缓慢阅读),入站缓冲区可能会增长到巨大的大小(我观察到 10 GB)。也许其他网络也是如此。我还没有找到一种有效分析进程内存转储的方法,不幸的是,我什至没有粗略的看法(并且会对实际答案非常感兴趣)。
-
检查直接 ByteBuffer 内存(可通过 MXBean
java.nio:type=BufferPool获得)。也可以试试Native Memory Tracking 功能。 -
我仍在运行 Java 7,所以看起来本机内存跟踪对我来说不是一个选项。不过看起来真的很有用。