要提供更多的信息,这里是我从Linux top命令中看到的,当堆大小设置为3G和7G时
xms& xmx = 3G(正常工作):
>启动tomcat之前:
Mem: 10129972k total,1135388k used,8994584k free,19832k buffers Swap: 2097144k total,0k used,2097144k free,56008k cached
> tomcat启动后:
Mem: 10129972k total,3468208k used,6661764k free,21528k buffers Swap: 2097144k total,143428k cached PID USER PR NI VIRT RES SHR S %cpu %MEM TIME+ COMMAND 2257 tomcat 20 0 5991m 1.9g 19m S 352.9 19.2 3:09.64 java
>启动负载10分钟后:
Mem: 10129972k total,6354756k used,3775216k free,21960k buffers Swap: 2097144k total,144016k cached PID USER PR NI VIRT RES SHR S %cpu %MEM TIME+ COMMAND 2257 tomcat 20 0 6549m 3.3g 10m S 332.1 34.6 16:46.87 java
xms& xmx = 7G(导致tomcat崩溃):
>启动tomcat之前:
Mem: 10129972k total,1270348k used,8859624k free,98504k buffers Swap: 2097144k total,74656k cached
> tomcat启动后:
Mem: 10129972k total,6415932k used,3714040k free,98816k buffers Swap: 2097144k total,144008k cached PID USER PR NI VIRT RES SHR S %cpu %MEM TIME+ COMMAND 2310 tomcat 20 0 9.9g 3.5g 10m S 0.3 36.1 3:01.66 java
>起动后10分钟(在tomcat死亡之前):
Mem: 10129972k total,9960256k used,169716k free,164k buffers Swap: 2097144k total,2095056k used,2088k free,3284k cached PID USER PR NI VIRT RES SHR S %cpu %MEM TIME+ COMMAND 2310 tomcat 20 0 10.4g 5.3g 776 S 9.8 54.6 14:42.56 java
Java和JVM版本:
Java(TM) SE Runtime Environment (build 1.7.0_21-b11) Java HotSpot(TM) 64-Bit Server VM (build 23.21-b01,mixed mode)
Tomcat版本:
6.0.36
Linux服务器:
Red Hat Enterprise Linux Server release 6.4 (Santiago)
所以我的问题是:
>为什么会发生这个问题?当JVM耗尽内存时,为什么没有抛出OutOfMemoryError?为什么直接使用互换?
>为什么顶级的RES显示java正在使用5.3G内存,有更多的内存消耗?
我一直在调查和搜索一段时间,仍然找不到这个问题的根本原因.非常感谢!
解决方法
Why would this issue happen? When JVM runs out of memory why is there no OutOfMemoryException thrown?
JVM内存不足,主机操作系统已经耗尽了与内存相关的资源,并且正在采取激烈的行动.操作系统无法知道当响应于更多内存的请求被告知“否”时,进程(在本例中为JVM)能够以有序的方式关闭.它已经很难杀死,否则整个操作系统挂起的风险很大.
无论如何,您没有看到OOME的原因是这不是OOME的情况.实际上,JVM已经被操作系统所占用的内存太多了,没有办法把它还原.这就是操作系统必须通过硬杀程序处理的问题.
And why does it go straight to using swap?
它使用交换,因为整个系统的总虚拟内存需求将不适合物理内存.这是UNIX / Linux操作系统的NORMAL行为.
Why top RES shows that java is using 5.3G memory,there’s much more memory consumed
RES号可能有点误导.他们所指的是进程当前使用的物理内存量…排除与其他进程共享或共享的东西. VIRT号码与您的问题更相关.它表示您的JVM正在使用10.4g的虚拟…这超出系统上可用的物理内存.
正如另一个答案所说,这是关于你关心你没有得到一个OOME.即使你得到一个,做任何事情也是不明智的. OOME可能对您的应用程序/容器造成附带损害,这些损坏很难被发现,并且难以从中恢复.这就是为什么OOME是错误而不是异常.
建议:
>不要尝试使用比具有物理内存的显存更多的虚拟内存,尤其是使用Java.当JVM运行完整的垃圾收集时,它将以随机顺序多次触及大多数VM页面.如果您明显地重新分配了内存,这可能会导致整个系统的性能下降.>增加系统的交换空间. (但这可能不会有帮助…)>不要尝试从OOME恢复.