我有一个 jvm,它的实际内存使用量远远超出了启动时的限制。它是一台 Sun VM:
root@jira:/opt/atlassian/jira/jre# ./bin/java -version
java version "1.6.0_26"
Java(TM) SE Runtime Environment (build 1.6.0_26-b03)
Java HotSpot(TM) Server VM (build 20.1-b02, mixed mode)
并且它已配置了最大堆 768MB ( -Xmx768m
) 和最大永久代 256MB ( -XX:MaxPermSize=256m
),但进程已远远超过 1GB,目前为 1.7GB。
我习惯于当存在内存泄漏的 Java 应用程序超出其限制时,通过 OutOfMemoryErrors 自行终止,而不是在 Linux OOMKiller 开始射击进程时被外部终止。
从ps
:
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
jira 23030 2.7 70.5 2181356 1457748 ? Sl Nov30 34:52 /opt/atlassian/jira/jre//bin/java -Djava.util.logging.config.file=/opt/atlassian/jira/conf/logging.properties -XX:MaxPermSize=256m -Xms256m -Xmx768m
有 1.5GB 并且它会持续增长直到 2GB 的盒子开始交换。
我对 JVM 内存限制有什么误解?
答案1
堆限制是提供给 Java 应用程序的 JVM 堆的限制(没有 Java 程序可以在堆上分配超过该量的空间),但不限制 Java 进程的大小(包括您限制的 JVM 堆,加上 JVM 本身分配的任何项目,加上堆栈(用于 JVM 和您的 Java 应用程序),加上我几乎肯定会遗漏的其他东西。
通常情况下,您不会看到超出设定限制的膨胀超过 10-15%,但可能存在病态情况,甚至可能存在内存泄漏或 Java 运行时本身的其他错误(祝你好运调试那头猪)。
如果你想在操作系统级别限制 Java 运行时的大小,你应该考虑ulimit
命令。JVM 可以妥善处理达到这些限制的情况。
答案2
这里有堆外区域,其中包括 JNI 代码和 Direct Byte 缓冲区分配的内存。您可以使用 来控制后者-XX:MaxDirectMemorySize
。