Java Process的常驻内存使用量(RSS)不断增长

我们最近对我们的生产系统的观察告诉我们,我们的Java容器的常驻内存使用量增长了。 针对这个问题,我们做了一些调查,理解为什么java进程比堆栈+线程栈+共享对象+代码caching+等消耗更多的内存,使用一些本地工具,如pmap。 因此,我们发现一些由本地进程(可能是使用malloc / mmap)分配的64M内存块(成对):

0000000000400000 4K rx-- /usr/java/jdk1.7.0_17/bin/java 0000000000600000 4K rw--- /usr/java/jdk1.7.0_17/bin/java 0000000001d39000 4108K rw--- [ anon ] 0000000710000000 96000K rw--- [ anon ] 0000000715dc0000 39104K ----- [ anon ] 00000007183f0000 127040K rw--- [ anon ] 0000000720000000 3670016K rw--- [ anon ] 00007fe930000000 62876K rw--- [ anon ] 00007fe933d67000 2660K ----- [ anon ] 00007fe934000000 20232K rw--- [ anon ] 00007fe9353c2000 45304K ----- [ anon ] 00007fe938000000 65512K rw--- [ anon ] 00007fe93bffa000 24K ----- [ anon ] 00007fe940000000 65504K rw--- [ anon ] 00007fe943ff8000 32K ----- [ anon ] 00007fe948000000 61852K rw--- [ anon ] 00007fe94bc67000 3684K ----- [ anon ] 00007fe950000000 64428K rw--- [ anon ] 00007fe953eeb000 1108K ----- [ anon ] 00007fe958000000 42748K rw--- [ anon ] 00007fe95a9bf000 22788K ----- [ anon ] 00007fe960000000 8080K rw--- [ anon ] 00007fe9607e4000 57456K ----- [ anon ] 00007fe968000000 65536K rw--- [ anon ] 00007fe970000000 22388K rw--- [ anon ] 00007fe9715dd000 43148K ----- [ anon ] 00007fe978000000 60972K rw--- [ anon ] 00007fe97bb8b000 4564K ----- [ anon ] 00007fe980000000 65528K rw--- [ anon ] 00007fe983ffe000 8K ----- [ anon ] 00007fe988000000 14080K rw--- [ anon ] 00007fe988dc0000 51456K ----- [ anon ] 00007fe98c000000 12076K rw--- [ anon ] 00007fe98cbcb000 53460K ----- [ anon ] 

我用0000000720000000来解释行3670016K指的是堆空间,我们使用JVM参数“-Xmx”来定义它的大小。 在那之后,这两个对就开始了,其中的总和正好是64M。 我们正在使用CentOS版本5.10(最终)64位拱和JDK 1.7.0_17。

问题是,这些块是什么? 哪个子系统分配这些?

更新:我们不使用JIT和/或JNI本机代码调用。

我遇到了同样的问题。 这是glibc> = 2.10的已知问题

治疗是设置这个envvariablesexport MALLOC_ARENA_MAX=4

IBM关于设置MALLOC_ARENA_MAX的文章https://www.ibm.com/developerworks/community/blogs/kevgrig/entry/linux_glibc_2_10_rhel_6_malloc_may_show_excessive_virtual_memory_usage?lang=en

Google for MALLOC_ARENA_MAX或在SO上search以查找大量参考。

您可能还想调整其他malloc选项以优化分配内存的低碎片:

 # tune glibc memory allocation, optimize for low fragmentation # limit the number of arenas export MALLOC_ARENA_MAX=2 # disable dynamic mmap threshold, see M_MMAP_THRESHOLD in "man mallopt" export MALLOC_MMAP_THRESHOLD_=131072 export MALLOC_TRIM_THRESHOLD_=131072 export MALLOC_TOP_PAD_=131072 export MALLOC_MMAP_MAX_=65536 

也有可能是本机内存泄漏。 一个常见的问题是由于没有closuresZipInputStream / GZIPInputStream而导致本地内存泄漏。

打开ZipInputStream一个典型方法是调用Class.getResource / ClassLoader.getResource然后调用java.net.URL实例上的openConnection().getInputStream()或调用Class.getResourceAsStream / ClassLoader.getResourceAsStream 。 人们必须确保这些河stream总是被closures。

您可以使用jemalloc通过指定MALLOC_CONF环境variables中的设置来启用malloc采样分析来debugging本机内存泄漏。 详细说明可在此博客文章中find: http : //www.evanjones.ca/java-native-leak-bug.html 。 这个博客文章还包含有关使用jemallocdebuggingJava应用程序中的本地内存泄漏的信息。

同一个博客还包含有关与ByteBuffers相关的另一个本地内存泄漏的信息。