一个带有-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运行参数(转)