【问题标题】:Tomcat was killed by kernelTomcat被内核杀死
【发布时间】:2014-10-20 11:56:38
【问题描述】:

我的tomcat突然自动关机。我检查了日志文件,发现它被杀死并显示消息:

kernel: Killed process 17420, UID 0, (java) total-vm:8695172kB, anon-rss:4389088kB, file-rss:20kB

我运行tomcat的设置是-Xms2048m -Xmx4096m -XX:NewSize=256m -XX:MaxNewSize=512m -XX:PermSize=256m -XX:MaxPermSize=1024m

运行命令“free -m”时我的系统是:

     total       used       free     shared    buffers     cached
Mem: 7859 7713 146 0 97 1600 
-/+ buffers/cache: 6015 1844 Swap: 0 0 0

我用“top -p”监控程序,结果如下

Cpu(s): 0.1%us, 0.0%sy, 0.0%ni, 99.9%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st Mem: 8048440k total, 7900616k used, 147824k free, 100208k buffers Swap: 0k total, 0k used, 0k free, 1640888k cached

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
4473 root 20 0 8670m 2.5g 6568 S 0.0 32.6 71:07.84 java

我的问题是:

1.为什么VIRT = 8670m(在“top -p”结果中)大于Mem:总计8048440k,但我的应用程序仍在运行?

  1. 为什么我的 tomcat 被内核杀死了?我看不出内存有什么奇怪的地方(运行时类似)

  2. 为避免发生此错误,我该怎么做?为什么?

【问题讨论】:

  • 您可能会在Server Fault 上获得更广泛的受众。

标签: java linux embedded-tomcat-7


【解决方案1】:
  1. Linux 操作系统有OOM 机制,当操作系统内存不足时。 OOM 将终止 cost max memory 程序(在大多数情况下,Linux Out Of Memory Management)。显然你的tomcat拥有最大内存。
  2. 如何解决?以我的经验,你必须观察操作系统的内存使用情况,你可以使用top命令来观察,并找到合适的进程。同时可以使用jvisualvm来观察tomcat的使用内存情况。

【讨论】:

  • OOM 杀手不会仅仅杀死最大的进程(尽管通常情况下是这样)。即使很大,它也有利于长时间运行的进程。如果 OOM 正在杀死真正的进程,那么无论如何您都处于困境中并且需要更多的 RAM/swap。 OOM 的目的是阻止失控的短期进程,这些进程卡在无限循环中吃掉 RAM。这就是为什么 OOM 杀手会首先使用大量 RAM 杀死短暂的进程。
【解决方案2】:

我知道在 Linux 中导致内核终止任务的唯一事情是 out of memory killerThis article from Oracle 可能是最近和相关的。

解决方案取决于系统上正在运行的其他内容。从您展示的内容来看,您的可用内存不足 2GB,但您的 Java 堆最大值已达到 4GB 左右。我们不知道您拍摄该快照时 Java 堆有多大。如果它的初始容量为 2GB,那么您可能会接近极限。同样根据您的格式,您没有交换空间可用作后备。

如果系统上有任何其他重要进程,则需要考虑它们的最大内存使用量。简短的回答是尽可能减少 Xmx 和 MaxPermSize,您必须分析您的负载以查看这是否可能或会导致不合理的 GC CPU 使用率。

一些注意事项:

  1. Java 使用的内存比堆多,它有内存用于运行 VM 本身的本机代码。
  2. Java 8 将 permgen 存储在堆外,因此我相信它会在 Xmx 参数之上添加内存,如果运行 Java 8,您可能需要注意。
  3. 当您减少内存限制时,您将达到 3 个范围:
    1. 远高于实际要求:没有明显差异
    2. 非常接近实际需求:服务器冻结/停止响应并使用 100% CPU(GC 开销)
    3. 低于实际要求:OutOfMemoryErrors
  4. 根据您的第一个问题,进程的 VM 大小可能超过 RAM+swap 大小。我记得在具有 256MB RAM 的无交换嵌入式系统上运行 Java 并看到 500MB 的内存使用并感到惊讶。一些原因:
    1. 在 Linux 中,您可以分配内存,但在写入之前不会真正使用它
    2. 内存映射文件(可能还有共享内存段之类的文件)计入此限制。我相信 Java 会将所有 jar 文件作为内存映射文件打开,因此包含在该 virt 大小中的是类路径上的所有 jar,包括 80MB 左右的 rt.jar。
    3. 共享对象可能计入 VIRT,但只占用一次空间(即,为许多进程加载的一个副本)
    4. 我听说过,但我现在找不到参考资料,Linux 实际上可以使用二进制文件/.so 文件作为只读“交换”空间,这意味着从本质上加载 2MB 二进制文件/so 将增加您的 VM大小增加了 2MB,但实际上并未使用所有 RAM,因为它仅从磁盘中分页实际访问的部分。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-04-29
    • 2013-04-24
    • 1970-01-01
    • 2017-06-17
    • 1970-01-01
    • 2018-01-11
    • 2021-10-24
    相关资源
    最近更新 更多