我的 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 但我的应用程序仍在运行?
为什么我的 tomcat 被内核杀死了?我没有看到内存有任何异常(它与运行时类似)
为避免此错误发生,我该怎么做以及为什么?
最佳答案
我唯一知道导致内核在 Linux 中终止任务的是 out of memory killer . This article from Oracle可能更新一些且相关。
解决方案取决于系统上还运行着什么。从您展示的内容来看,您的可用内存少于 2GB,但您的 Java 堆最大值达到了 4GB 左右。我们不知道在您拍摄该快照时 Java 堆有多大。如果它的初始大小为 2GB,那么您的运行速度可能接近极限。同样根据您的格式,您没有交换空间可用作后备。
如果系统上有任何其他重要进程,则需要考虑它们的最大内存使用量。简短的回答是尽可能减少 Xmx 和 MaxPermSize,您必须分析您的负载以查看这是否可能或是否会导致不合理的 GC CPU 使用率。
一些注意事项:
- Java 使用的内存比堆多,它有内存用于运行 VM 本身的 native 代码。
- Java 8 将 permgen 存储在堆外,因此我相信它会在 Xmx 参数之上添加内存,如果运行 Java 8,您可能需要注意这一点。
- 当您降低内存限制时,您将达到 3 个范围:
- 远高于实际要求:无明显差异
- 非常接近真实需求:服务器卡住/停止响应并使用 100% CPU(GC 开销)
- 低于实际要求:OutOfMemoryErrors
- 根据您的第一个问题,进程的 VM 大小有可能超过 RAM+swap 大小。我记得在具有 256MB RAM 的无交换嵌入式系统上运行 Java,看到 500MB 的内存使用情况并感到惊讶。一些原因:
- 在 Linux 中,您可以分配内存,但在写入之前不会实际使用
- 内存映射文件(可能还有共享内存段之类的东西)计入此限制。我相信 Java 将所有 jar 文件作为内存映射文件打开,因此包含在 virt 大小中的是类路径中的所有 jar,包括 80MB 左右的 rt.jar。
- 共享对象可能计入 VIRT,但只占用空间一次(即为多个进程加载的一个副本)
- 我听说过,但我现在找不到引用资料,Linux 实际上可以使用二进制文件/.so 文件作为只读“交换”空间,这意味着基本上加载 2MB 二进制文件/so 将增加您的 VM大小增加 2MB,但实际上并未使用所有 RAM,因为它仅从磁盘调入实际访问的部分。
关于java - Tomcat 被内核杀死,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25517998/