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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为啥JAVA进程占用内存会超过Xmx设置相关的知识,希望对你有一定的参考价值。

参考技术A Xmx 不是说内存使用不会超过这个值,而是说超过或接近这个值会触发OLD GC。当触发Young GC 后部分对象可能会从年轻带进入老年代。但老年代这个时候不一定有足够的内存来保存这些对象。老年代如何判定内存是否足够。 就是Xmx减去已经用了的内存再减去本次须要的内存。 如果不够就会触发OLD GC。哎,越解释越多。你就记着这个值就是建议内存最大使用值。 如果内存使用超过这个值,jvm认为还有内存可以使用,也会将对象一直往堆里面放,不过会频繁触发 FULL GC 参考技术B

Xmx设置的是最大堆内存,其他的栈,jvm什么的也要占用内存的,看看这个图就懂了

JVM 内存组成

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

【中文标题】Java 进程占用的内存超过其最大堆大小【英文标题】:Java process taking more memory than its max heap size 【发布时间】:2014-07-10 07:00:30 【问题描述】:

我在一台机器上运行两个 tomcat 服务器(内存大小 16GB),内存设置如下。

JAVA_MEM_OPTIONS="-Xmx4096M -Xms4096M -XX:NewSize=512M -XX:MaxNewSize=512M  -XX:PermSize=256M -XX:MaxPermSize=256M -verbose:gc -XX:+PrintGCTimeStamps -XX:+PrintGCDetails  -XX:+UseConcMarkSweepGC -XX:+PrintGCApplicationConcurrentTime -XX:+PrintGCApplicationStoppedTime -XX:SoftRefLRUPolicyMSPerMB=5 -XX:+HeapDumpOnOutOfMemoryError -XX:+DisableExplicitGC"

顶部结果显示 java 进程使用了​​ 46.5%(7.44 GB) 和 39.2%(6.24 GB) 的内存。

Tasks: 120 total,   1 running, 119 sleeping,   0 stopped,   0 zombie
Cpu(s):  7.8%us,  0.4%sy,  0.0%ni, 90.9%id,  0.2%wa,  0.0%hi,  0.7%si,  0.0%st
Mem:  16424048k total, 16326072k used,    97976k free,    28868k buffers
Swap:  1959920k total,  1957932k used,     1988k free,  1082276k cached

PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                                                                                                                         
26275 user1      25   0 8007m 7.3g 7832 S 13.6 46.5 785:31.89 java                                                                                                                                            
28050 user2      25   0 7731m 6.1g  13m S  9.0 39.2 817:10.47 java  

GC 日志显示每个 java 进程仅使用 4GB 内存。一旦系统内存使用量上升,它就永远不会下降。

user1 - java process

89224.492: [GC 89224.492: [ParNew: 443819K->17796K(471872K), 0.0367070 secs] 2032217K->1608465K(4141888K), 0.0368920 secs] [Times: user=0.13 sys=0.00, real=0.03 secs] 
89228.247: [GC 89228.247: [ParNew: 437252K->22219K(471872K), 0.0607080 secs] 2027921K->1615327K(4141888K), 0.0609240 secs] [Times: user=0.15 sys=0.00, real=0.06 secs] 

user2 - java process

89202.170: [GC 89202.170: [ParNew: 444989K->22909K(471872K), 0.0510290 secs] 2361057K->1945258K(4141888K), 0.0512370 secs] [Times: user=0.19 sys=0.00, real=0.05 secs] 
89207.894: [GC 89207.894: [ParNew: 442365K->15912K(471872K), 0.0422190 secs] 2364714K->1945162K(4141888K), 0.0424260 secs] [Times: user=0.15 sys=0.00, real=0.04 secs]

当堆内存设置为 4GB 时,java 进程如何使用这么多内存。如何调试问题的原因。

PS:有时我正在从 java 代码执行 shell 脚本。会不会导致这样的问题?

【问题讨论】:

Java 进程不仅有堆。还有其他东西要存储。 可能重复的候选人:***.com/questions/10818356/…、***.com/questions/6527131/…、***.com/questions/11768615/…、***.com/questions/9145769/… 【参考方案1】:

有几种情况:

    拥有大量线程。线程堆栈空间分配在堆/永久空间之外。要设置为每个线程分配的内存,请使用 -Xss 选项。 使用 JNI。看看这个问题Java app calls C++ DLL via JNI; how best to allocate memory?

可能还有更多,在实践中,第一种情况最有可能是原因。

【讨论】:

以上是关于为啥JAVA进程占用内存会超过Xmx设置的主要内容,如果未能解决你的问题,请参考以下文章

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

Java 进程中有哪些组件会占用内存?

java 进程消耗内存只增不减

jvm高手来啊,xms和xmx一样出现问题.

为啥Java会产生这么多进程?

JVM —— Java 对象占用空间大小计算