我在一个tomcat服务器上执行负载测试。服务器具有10G物理内存和2G交换空间。堆大小(xms和xmx)以前设置为3G,服务器工作正常。由于我仍然看到了大量空闲内存,而且性能不佳,所以我将堆大小增加到7G,并再次运行负载测试。这一次,我观察到物理内存很快就被吞噬了,系统开始消耗交换空间。后来,tomcat在交换空间耗尽后崩溃了。我在启动tomcat时包含了-XX:+HeapDumpOnOutOfMemoryError,但没有得到任何堆转储。当我检查/var/log/messages时,我看到了kernel: Out of memory: Kill process 2259 (java) score 634 or sacrifice child。
为了提供更多信息,下面是我在将堆大小设置为3G和7G时从Linux top命令中看到的
xms&xmx = 3G (运行良好):
xms&xmx = 7G (导致tomcat崩溃的原因):
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.36Linux服务器:
Red Hat Enterprise Linux Server release 6.4 (Santiago)所以我的问题是:
top RES显示java使用5.3G内存,占用的内存更多?我已经调查了一段时间,仍然找不到这个问题的根本原因。非常感谢!
发布于 2013-06-20 00:02:40
为何会出现这种情况呢?当JVM耗尽内存时,为什么没有抛出OutOfMemoryException?
内存不足的不是JVM。正是主机操作系统耗尽了与内存相关的资源,并且正在采取激烈的行动。操作系统无法知道进程(在本例中是JVM)在响应对更多内存的请求时能够有序地关闭“否”。它必须硬杀一些东西,否则会有严重的风险,整个操作系统挂。
无论如何,你没有看到OOME的原因是,这不是OOME的情况。实际上,操作系统已经为JVM提供了太多的内存,因此无法收回它。这就是操作系统必须通过硬杀过程来解决的问题。
为什么要直接使用交换呢?
它使用交换,因为整个系统的总虚拟内存需求将不适合物理内存。这是UNIX / Linux操作系统的正常行为。
为什么top RES显示java正在使用5.3G内存,占用的内存要多得多
RES数字可能有点误导。它们所指的是进程当前使用的物理内存量.排除与其他流程共享或共享的内容。VIRT号与您的问题更相关。它说你的JVM正在使用10.4g的虚拟.这比系统上可用的物理内存还要多。
正如另一个答案所指出的,这关系到你没有得到一个OOME。即使您得到了一个,使用它做任何事情都是不明智的。OOME很容易对您的应用程序/容器造成很难检测和难以恢复的附带损害。这就是为什么OOME是Error而不是Exception的原因。
建议:
发布于 2013-06-19 23:46:18
您可能在同一台计算机上有其他也使用内存的进程。看起来,在机器严重耗尽RAM和交换之前,您的java进程达到了5.3GB。(其他进程可能使用12 GB-5.3GB= 6.7GB),因此linux内核牺牲了java进程以保持其他进程的运行。java内存限制永远不会达到,因此您不会得到OutOfMemoryException。
考虑需要在整个机器上运行的所有进程,并相应地调整Xmx设置(足够为所有其他进程留出空间)。也许是5gb?
在任何情况下,计算被传递的OutOfMemoryExceptions都是非常糟糕的代码气味。如果我没记错的话,即使获得一个OutOfMemoryException,也可能使JVM处于“所有押注都关闭”的状态,并且可能会重新启动而不会变得不稳定。
发布于 2022-07-30 10:15:03
一天晚上,我离开了这个系统,第二天早上,它自己修好了!没有任何变化。甚至不需要重新开始。
https://stackoverflow.com/questions/17203111
复制相似问题