Out of memory:Kill process or sacrifice child

JAVA herman 69浏览

这个错误同样不常见,很少有人遇到,但并不代表它不存在!今天就来说说 Out of memory: Kill process or sacrifice child。

我们知道,操作系统(operating system)构建在进程(process)的基础上。进程由内核作业(kernel jobs)进行调度和维护,其中有一个内核作业称为 “Out of memory killer(OOM终结者)”。

Out of memory killer 在可用内存极低的情况下会杀死某些进程。只要达到触发条件就会激活,选中某个进程并杀掉。通常采用启发式算法,对所有进程计算评分(heuristics scoring),得分最低的进程将被 kill 掉。因此 Out of memory: Kill process or sacrifice child 和前面所讲的 OutOfMemoryError 都不同,因为它既不由JVM触发,也不由JVM代理, 而是系统内核内置的一种安全保护措施。

Out of memory: Kill process or sacrifice child

如果可用内存(含swap)不足,就有可能会影响系统稳定,这时候 Out of memory killer 就会设法找出流氓进程并杀死他,从而引起 Out of memory: kill process or sacrifice child 错误。

默认情况下,Linux kernels(内核)允许进程申请的量超过系统可用内存。这是因为,在大多数情况下,很多进程申请了很多内存,但实际使用的量并没有那么多。

打个简单的比喻:宽带租赁的服务商,可能他的总带宽只有 10Gbps,但却卖出远远超过 100 份以上的 100Mbps 带宽,原因是多数时候,宽带用户之间是错峰的, 而且不可能每个用户都用满服务商所承诺的带宽。

这样的话,可能会有一个问题,假若某些程序占用了大量的系统内存,那么可用内存量就会极小,导致没有内存页面(pages)可以分配给需要的进程。可能这时候会出现极端情况,就是 root 用户也不能通过 kill 来杀掉流氓进程。为了防止发生这种情况,系统会自动激活 killer,查找流氓进程并将其杀死。

现在我们知道了为什么会发生这种问题,那为什么是半夜5点钟触发 “killer” 发报警信息给你呢?通常触发的原因在于操作系统配置。例如:/proc/sys/vm/overcommit_memory 配置文件的值, 指定了是否允许所有的 malloc() 调用成功。请注意,在各操作系统中,这个配置对应的 proc 文件路径可能不同。

过量使用(overcommitting)配置,允许流氓进程申请越来越多的内存,最终惹得 ”Out of memory killer“ 出来搞事情。

下面我们看一个示例,产生 Out of memory: kill process or sacrifice child 错误。

public class OOM {
// 业余草:www.xttblog.com
public static void main(String[] args){
  java.util.List<int[]> l = new java.util.ArrayList();
  for (int i = 10000; i < 100000; i++) {
      try {
        l.add(new int[100000000]);
      } catch (Throwable t) {
        t.printStackTrace();
      }
    }
  }
}

在 Linux 上(如最新稳定版的 Ubuntu)编译并执行上面的代码,最终在系统日志中(如 /var/log/kern.log 文件)可能会看到类似下面的信息:

Jun  4 07:41:59 plumbr kernel: 
    [70667120.897649]
    Out of memory: Kill process 29957 (java) score 366 or sacrifice child
Jun  4 07:41:59 plumbr kernel: 
    [70667120.897701]
    Killed process 29957 (java) total-vm:2532680kB, anon-rss:1416508kB, file-rss:0kB

如果需要调整 swap 的大小,可以使用下面的命令:

swapoff -a 
dd if=/dev/zero of=swapfile bs=1024 count=655360
mkswap swapfile
swapon swapfile

解决这个问题的办法有多种。最简单的办法就是将系统迁移到内存更大的实例中。另外,还可以通过 OOM killer 调优,或者做负载均衡(水平扩展,集群),或者降低应用对内存的需求。

参考资料

业余草公众号

最后,欢迎关注我的个人微信公众号:业余草(yyucao)!可加QQ1群:135430763(2000人群已满),QQ2群:454796847,QQ3群:187424846。QQ群进群密码:xttblog,想加微信群的朋友,可以微信搜索:xmtxtt,备注:“xttblog”,添加助理微信拉你进群。备注错误不会同意好友申请。再次感谢您的关注!后续有精彩内容会第一时间发给您!原创文章投稿请发送至532009913@qq.com邮箱。商务合作可添加助理微信进行沟通!

本文原文出处:业余草: » Out of memory:Kill process or sacrifice child