首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Tomcat进程在交换空间用完后被Linux内核杀死;不要出现JVM OutOfMemory错误。

Tomcat进程在交换空间用完后被Linux内核杀死;不要出现JVM OutOfMemory错误。
EN

Stack Overflow用户
提问于 2013-06-19 23:41:23
回答 3查看 11.3K关注 0票数 14

我在一个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 (运行良好):

  • 在开始做猫之前: 内存: 10129972k,使用1135388k,免费8994584k,19832k缓冲区交换: 2097144k,0k使用,2097144k免费,56008k缓存
  • 在启动tomcat之后: 内存: 10129972k,使用3468208k,免费6661764k,21528k缓冲区交换: 2097144k,0k使用,2097144k免费,143428k缓存PID用户PR SHR %MEM TIME+命令2257猫205991g 19m S 352.9 19.2 3:09.64 java
  • 启动负荷10分钟后: 内存: 10129972k,使用6354756k,免费3775216k,21960k缓冲区交换: 2097144k,0k使用,2097144k免费,144016k缓存PID用户PR NI VIRT SHR %MEM TIME+命令2257猫206549m 3.3g 10m S 332.1 34.6 16:46.87 java

xms&xmx = 7G (导致tomcat崩溃的原因):

  • 在开始做猫之前: 内存: 10129972k总计,1270348k使用,8859624k免费,98504k缓冲区交换: 2097144k,0k使用,2097144k免费,74656k缓存
  • 在启动tomcat之后: 内存: 10129972k总计,6415932k使用,3714040k免费,98816k缓冲区交换: 2097144k,0k使用,2097144k免费,144008k缓存PID用户PR NI VIRT SHR %CPU %MEM TIME+命令2310 tomcat 20 0 9.9g 3.5g 10m S 0.3 36.1 3:01.66 java
  • 在启动负载10分钟后(就在tomcat被杀之前): 内存: 10129972k,使用9960256k,169716k空闲,164 k缓冲区交换: 2097144k,2095056k使用,2088k空闲,3284 k缓存PID用户PR NI VIRT %CPU %MEM TIME+命令2310 tomcat 20 10.4g 5.3g 776 S 9.8 54.6 14:42.56 java

Java和JVM版本:

代码语言:javascript
复制
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版本:

代码语言:javascript
复制
6.0.36

Linux服务器:

代码语言:javascript
复制
Red Hat Enterprise Linux Server release 6.4 (Santiago)

所以我的问题是:

  1. 为何会出现这种情况呢?当JVM耗尽内存时,为什么没有抛出OutOfMemoryError?为什么要直接使用交换呢?
  2. 为什么top RES显示java使用5.3G内存,占用的内存更多?

我已经调查了一段时间,仍然找不到这个问题的根本原因。非常感谢!

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 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的原因。

建议:

  • 不要尝试使用比物理内存更多的虚拟内存,尤其是使用Java。当JVM运行一个完整的垃圾收集时,它将按随机顺序多次访问它的大部分VM页面。如果你过度分配你的内存,这很容易造成打击,这会扼杀整个系统的性能。
  • 增加系统的交换空间。(但这可能没有帮助.)
  • 不要试图从海洋生态系统中恢复过来。
票数 9
EN

Stack Overflow用户

发布于 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处于“所有押注都关闭”的状态,并且可能会重新启动而不会变得不稳定。

票数 1
EN

Stack Overflow用户

发布于 2022-07-30 10:15:03

一天晚上,我离开了这个系统,第二天早上,它自己修好了!没有任何变化。甚至不需要重新开始。

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17203111

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档