java - Tomcat 被内核杀死

标签 java linux embedded-tomcat-7

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

内核:终止进程 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. 为避免此错误发生,我该怎么做以及为什么?

最佳答案

我唯一知道导致内核在 Linux 中终止任务的是 out of memory killer . This article from Oracle可能更新一些且相关。

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

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

一些注意事项:

  1. Java 使用的内存比堆多,它有内存用于运行 VM 本身的 native 代码。
  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,因为它仅从磁盘调入实际访问的部分。

关于java - Tomcat 被内核杀死,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25517998/

相关文章:

linux - 为什么在发送密码后使用 Expect 自动化 SFTP 会挂起?

Gradle Spring Boot 项目在 Tomcat 中无法作为 WAR 工作

java - 实现一个 kotlin 泛型函数,从复杂的 java 对象中检索特定字段

java - Android 蓝牙设备选择器使用

java - 如何使用 Sikuli Java Standalone jar 输入文本?

linux - 使用 Linux 可加载内核模块拦截系统调用(劫持)

linux - 运行python时如何使shell脚本阻塞?

java - 嵌入式 tomcat 权限被拒绝

java - tomcat7-maven-plugin 无法从 react 器中找到依赖项

java - 在 Web 应用程序中运行时动态加载 Spring 上下文