11

所以每隔几天我在 Ubuntu 上的 java 进程就会被自动杀死,我不知道为什么。

我的盒子有 35.84 GB 的 RAM,当我启动我的 Java 进程时,我将 -Xmx28g 参数传递给它,所以它应该使用小于可用的最大 RAM 的方式。

我运行 jstat 如下:

# jstat -gccause -t `pgrep java` 60000

在进程被杀死之前 jstat 的最后几行输出是:

Time     S0     S1     E      O      P       YGC   YGCT       FGC FGCT     GCT     LGCC                 GCC
14236.1  99.98   0.00  69.80  99.40  49.88   1011  232.305    11  171.041  403.347 unknown GCCause      No GC
14296.2  93.02   0.00  65.79  99.43  49.88   1015  233.000    11  171.041  404.041 unknown GCCause      No GC
14356.1  79.20   0.00  80.50  99.55  49.88   1019  233.945    11  171.041  404.986 unknown GCCause      No GC
14416.2   0.00  99.98  24.32  99.64  49.88   1024  234.945    11  171.041  405.987 unknown GCCause      No GC

这似乎是这次 /var/log/syslog 中发生的事情:https ://gist.github.com/1369135

除了我的 java 应用程序之外,这台服务器上实际上没有运行任何东西。这是怎么回事?

编辑:我正在运行 java 版本 1.6.0_20,我在启动时传递给 java 的唯一值得注意的参数是“-server -Xmx28g”。我没有使用应用程序服务器,但我的应用程序嵌入了“简单 Web 框架”。

4

5 回答 5

8

假设问题是 OOM 杀手,那么它已经杀死了你的进程,拼命地试图让操作系统在严重的内存短缺危机中运行。

我会得出结论:

  • 您的 JVM 实际上使用了超过 28Gb 的内存;即你有大量的非堆内存使用,并且

  • 操作系统没有配置足够的交换空间。

我会尝试添加更多交换空间,以便操作系统可以在紧急情况下交换部分应用程序。

或者,减小 JVM 的堆大小。


请注意,“-Xmx ...”设置最大堆大小,而不是 JVM 可以使用的最大内存量。JVM 将一些东西放在堆外,包括诸如线程堆栈的内存和应用程序正在使用的内存映射文件之类的东西。


系统日志确认它是工作中的 OOM 杀手。

链接的系统日志以什么方式这么说?

它是这样说的:

Nov 15 13:53:49 ip-10-71-94-36 kernel: [3707038.606133] Out of memory: kill process 6368 (run.sh) score 4747288 or a child
Nov 15 13:53:49 ip-10-71-94-36 kernel: [3707038.606146] Killed process 9359 (java)

控制台说 java 被杀死了,而不是它退出了。

正确的。它被操作系统的OOM杀手杀死。

如果它内存不足,它通常会抛出 OutOfMemory 异常,但它没有。

如果你填满了 Java 堆,就会发生这种情况。

这不是这里发生的事情。实际问题是没有足够的物理 RAM 来容纳 Java 堆。OOM杀手处理它......

我正在运行如此巨大的堆,因为我需要存储数百万个对象,每个对象都需要几千字节的 RAM。

不幸的是,您尝试使用的 RAM 比系统上可用的 RAM 多。这会导致虚拟内存抖动,影响整个操作系统。

当系统开始严重抖动时,OOM 杀手(而不是 JVM)将您的 Java 进程识别为问题的原因。然后它会杀死它(使用 SIGKILL)以保护系统的其余部分。如果没有,整个系统就有可能完全锁定并需要硬重启。


最后,你说:

我的盒子有 35.84 GB 的 RAM ...

这是一个相当奇怪的值。32 GiB 是 34,359,738,368 字节或 34.35 GB。

但基于这一点和观察到的行为,我怀疑这是可用的虚拟内存而不是物理 RAM。或者,您的“盒子”可以是在管理程序级别启用 RAM 过量使用的虚拟机。

于 2011-11-16T03:13:31.117 回答
7

欢迎使用 OOM-killer,这是一个 Linux 的“功能”,它是无处不在的大内存应用程序的祸根。没有简单的方法可以处理,只需谷歌搜索并开始阅读和分析。

虽然我无法简明扼要地解释 OOM 杀手的恶作剧,但我记得关键的调整参数称为“swappiness”。在我们的一台大型服务器上,我们有:

/etc/sysctl.conf:vm.swappiness=20

阅读http://www.gentooexperimental.org/~patrick/weblog/archives/2009-11.html

于 2011-11-16T03:14:46.503 回答
3

你用的是什么JVM?什么应用服务器?您可能分配了太多内存,这可能会产生问题 - 垃圾收集器可能无法完成其工作。

我不确定这是否是您的情况,但我发现这篇文章非常有趣,它解释了 Linux 过度使用内存的方式。

于 2011-11-16T03:14:24.843 回答
1

哇,你真的可以拥有 28 GB 的堆吗?可能您应该尝试减少它,将其保持在我认为不超过 RAM 的 50%(所以 ~18 GB,甚至可能是 15 GB)。再加上 171 个 Full GC 就很多了!这个应用程序运行了多长时间?2-3 天内 171 听起来很大。顺便说一句,gist 在终止之前表示 OOM - 我认为减少堆会解决它(您可能会限制 JVM 扩展本机空间)。尝试调整各种参数,如果需要,尝试堆栈大小,例如 (-Xss)。检查最大烫发大小和其他部分。它是一个内存问题,它可能不一定是堆。

于 2011-11-16T03:13:34.737 回答
1

Ubuntu 有一个“看门狗”进程,当内存不足时会杀死其他进程。请参阅手册页: http: //manpages.ubuntu.com/manpages/natty/man8/watchdog.8.html

于 2013-05-17T20:12:22.693 回答