一个带有-Xmx1024m的Java进程怎么会占用3GB的常驻内存呢?

Posted

技术标签:

【中文标题】一个带有-Xmx1024m的Java进程怎么会占用3GB的常驻内存呢?【英文标题】:How can a Java process with -Xmx1024m occupy 3GB resident memory? 【发布时间】:2009-03-26 15:59:33 【问题描述】:

它是 Websphere6.1、Solaris 10、JDK 1.5.0_13 上的 Java Web 应用程序。我们将最大堆大小设置为 1024m。 jmap 显示堆状态是健康的。堆内存使用率仅为 57%。根本没有 OutOfMemory。

但是我们从 ps 看到这个 java 进程的 RSS 非常高(3GB)。 pmap 显示一块 1.9G 的私有内存。

3785:/dmwdkpmmkg/was/610/java/bin/java -server -Dwas.status.socket=65370 -X 地址千字节 RSS 匿名锁定 Pgsz 模式映射文件 ... 0020A000 2008 2008 2008 - 8K rwx-- [堆] 00400000 1957888 1957888 1957888 - 4M rwx-- [堆] 8D076000 40 40 40 - 8K rw--R [堆栈 tid=10786] ...

这是原生代码中的 C 堆内存泄漏吗?推荐什么方法来找出根本原因?

【问题讨论】:

【参考方案1】:

这个来自 Sun 的Troubleshooting Memory Leaks 文档可能会帮助您找到导致 RSS 高的问题,特别是在第 3.4 节中。

当您运行 Websphere 时,也许您可​​以在您的 VM 上使用 -memorycheck。详情见here。

这不一定是本机代码的泄漏。如果您查看here,在 Solaris 上可能存在文件保持打开的问题。

这只是一堆链接和提示,但可能有助于追踪您的问题。

【讨论】:

他们很有帮助。虽然 -memorycheck 似乎仅适用于 IBM JDK? Solaris 上没有 IBM JDK,只有 SUN JDK,对吧? 不知道,我没有使用 Solaris 的经验,但可能没有……也许 IBM JDK 将与 Websphere 一起提供,因为它也来自 IBM。我就是这么想的。【参考方案2】:

即使没有本机内存泄漏(如未关闭的 zip 资源),也可能会发生这种情况。

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

的一个已知问题

解决方法是设置这个环境变量 export MALLOC_ARENA_MAX=4

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

谷歌 MALLOC_ARENA_MAX 或在 SO 上搜索以找到很多参考资料。

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

# tune glibc memory allocation, optimize for low fragmentation
# limit the number of arenas
# requires glibc >= 2.16 since there was a bug in 
# MALLOC_ARENA_TEST parameter handling that cause MALLOC_ARENA_MAX not to work
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

您可以调用本机 malloc_info 函数来获取有关内存分配的信息。这是using JNA to call the native malloc_info method 的示例。

【讨论】:

谢谢拉里!你的回答很有说服力。但是,我不再需要验证应用程序和 solaris env - 起源问题是 6 年前提出的 :) 但是还是感谢您让我知道。这个问题对我来说一直很神秘。 查看这个答案:***.com/a/35610063,它有更多关于 Java 原生内存泄漏的细节。【参考方案3】:

堆大小 os Java 堆大小,还有 VM 和其他库是进程的一部分。

尝试运行具有 1024m 堆大小和“for(;;)”的 Hello World,看看它占用了多少。这应该为您提供总体内存使用情况的基准。

【讨论】:

【参考方案4】:

您在使用 JNI 库吗?我不确定本机代码如何分配 RAM,但这就是我开始寻找的地方。

【讨论】:

以上是关于一个带有-Xmx1024m的Java进程怎么会占用3GB的常驻内存呢?的主要内容,如果未能解决你的问题,请参考以下文章

“-Xmx1024m -Xms1024m -Xmn512m -Xss256k”——Java运行参数(转)

为啥JAVA进程占用内存会超过Xmx设置

“-Xmx1024m -Xms1024m -Xmn512m -Xss256k”——Java运行参数

Java 进程占用的内存超过其最大堆大小

tomcat启动进程突然停止无错误日志输出

kettle内存占用怎么解决?