Tomcat服务内存超过max无故障

Did*_*jit 1 java memory tomcat heap-memory

我已经阅读了大量帖子,但显然我在理解中遗漏了一些东西。我有一个 Tomcat 服务,它安装了:

--JvmMx=1000
--JvmMs=128
Run Code Online (Sandbox Code Playgroud)

我已经通过以下调用验证了这些设置是否成功:

PsExec.exe -s {jdk}\bin\jinfo.exe -flag MaxHeapSize {pid}
Run Code Online (Sandbox Code Playgroud)

但是,此服务的 tomcat7.exe 进程持续增长,超过此最大值的 3 倍或更多倍,直到它使服务器爬行。奇怪的是,这只是一台服务器上的问题;在其他任何地方,它都相当稳定,并保持在限制之下。我还在我的开发环境中寻找内存泄漏,但没有找到。

为了调试这个,我试过像这样强制 GC:

 PsExec.exe -s {jdk}\bin\jcmd.exe {pid} GC.run
Run Code Online (Sandbox Code Playgroud)

但这似乎没有效果。所以接下来我通过将它添加到安装中来设置 jconsole 监控:

tomcat7.exe //US//%SERVICE_NAME% ++JvmOptions="-Dcom.sun.management.jmxremote"
tomcat7.exe //US//%SERVICE_NAME% ++JvmOptions="-Dcom.sun.management.jmxremote.port=8086"
tomcat7.exe //US//%SERVICE_NAME% ++JvmOptions="-Dcom.sun.management.jmxremote.ssl=false"
tomcat7.exe //US//%SERVICE_NAME% ++JvmOptions="-Dcom.sun.management.jmxremote.authenticate=false"
Run Code Online (Sandbox Code Playgroud)

现在(当然!)它很乖。GC 显然工作正常,进程内存保持在限制以下。

我很困惑。最大堆是 1 GB,永久内存是 90 MB,堆栈大小是默认的,所以大约 128 KB?而没有增长的线程数“只有”67。那么进程内存如何上升到3+GB呢?为什么它不抛出内存不足异常?

即使是现在,根据 jconsole 的“行为良好”服务仅使用大约 50 MB 的堆,在 57 个线程上运行。然而,任务管理器显示 71 个线程使用 800 MB。我认为差异是由于 Tomcat 造成的,是吗?请帮助我填补我的理解空白。

Chr*_*ltz 5

Java 使用的内存不仅仅是 Java 堆空间所需的内存。它被称为“本机内存”,不包括在您提到/检查的任何内存空间中。

这篇文章会让你大开眼界:http : //www.evanjones.ca/java-native-leak-bug.html

(FWIW,设置-Xms-Xmx一个服务器进程,以不同的价值观根本就是浪费时间。将它们设置为相同的值,使堆并不需要重新大小的一堆在路上的时间“向上”的最大堆大小。如果您要为服务器进程提供例如 1GiB,您最好立即允许​​使用它。)