繁体   English   中英

Java进程可能由于Linux OOM杀手而被杀死

[英]Java process getting killed likely due to Linux OOM killer

我的Java进程在一段时间后被杀死。 并行GC的堆设置为最小-2 Gb和最大3 Gb。 通过pmap命令,它显示了40多个64Mb匿名块,这似乎是导致Linux OOM杀手的原因。

错误

没有足够的内存,Java运行时环境无法继续。 本机内存分配(mmap)无法映射用于提交保留内存的71827456字节。 可能的原因:系统的物理RAM或交换空间不足在32位模式下,达到了进程大小限制可能的解决方案:减少系统上的内存负载增加物理内存或交换空间检查交换后备存储是否已满使用64位Java在64位OS上减小Java堆大小(-Xmx / -Xms)减小Java线程数减小Java线程堆栈大小(-Xss)使用-XX:ReservedCodeCacheSize =设置更大的代码缓存此输出文件可能被截断或不完整。

内存不足错误(os_linux.cpp:2673),pid = 21171,tid = 140547280430848

JRE版本:Java(TM)SE运行时环境(8.0_51-b16)(内部版本1.8.0_51-b16)Java VM:Java HotSpot(TM)64位服务器VM(25.51-b03混合模式linux-amd64压缩oops)失败写核心转储。 核心转储已被禁用。 要启用核心转储,请在再次启动Java之前尝试“ ulimit -c unlimited”

尝试将堆与G1GC一起减少到最小512 Mb和最大2 Gb,我们看到18周围的64 Mb块数量有限,并且该进程没有被杀死。

但是在最小2Gb和最大3Gb的堆以及G1GC的情况下,我们看到了大量的64 Mb块。

根据文档,对于具有2个内核的64位系统,最大64Mb块(malloc区域)的数量可以为2 * 8 = 16,但我们看到的数量超过了16。

看起来不像Linux OOM杀手。

您描述的症状表明您已用完物理内存和交换空间。 实际上,错误消息确切地表明:

没有足够的内存,Java运行时环境无法继续。 本机内存分配(mmap)无法映射用于提交保留内存的71827456字节。 可能的原因:

  • 系统没有物理RAM或交换空间

  • 在32位模式下,达到了进程大小限制

虚拟内存系统通过将虚拟地址空间映射到物理RAM页和磁盘页的组合来工作。 在任何给定时间,实时页面都可以驻留在RAM或磁盘中。 如果应用程序要求更多的虚拟内存(例如,使用mmap调用),则OS可能不得不说“不能”。 那就是发生了什么。

解决方案如消息所示:

  • 获得更多的RAM,
  • 增加交换空间的大小,或
  • 以各种方式限制应用程序请求的内存量。

G1GC参数(除了最大堆大小之外)基本上无关紧要。 我的理解是,最大堆大小是Java堆被允许占用的(虚拟)内存总量。


那么,如果这不是Linux OOM的杀手er,那是什么?

实际上,OOM杀手是一种机制,用于识别由于执行过多分页而导致危险性能问题的应用程序。 正如我在开始时提到的那样,虚拟内存由驻留在RAM或磁盘中的页面组成。 通常,应用程序不知道任何VM页是否驻留在RAM中。 操作系统只负责它。

如果应用程序尝试使用(读取或写入)非RAM驻留的页面,则会发生“页面错误”。 操作系统通过以下方式处理此问题:

  • 挂起应用程序线程
  • 查找备用RAM页面
  • 将磁盘页面读取到RAM页面中
  • 恢复应用程序线程...然后可以访问该地址处的内存。

另外,操作系统需要维护“干净”页面的池。 即RAM和磁盘版本相同的页面。 通过扫描已被应用程序修改的法师并将其写入磁盘来完成此操作。

如果应用程序表现得“很好”,则分页活动的数量相对较少,并且线程不会经常挂起。 但是,如果分页很多,那么您可能会遇到分页I / O成为瓶颈的情况。 在最坏的情况下,整个系统将锁定。

OOM杀手的目的是识别导致危险的高寻呼率的进程,并...杀死它们。

如果JVM进程被OOM杀手杀死,它就没有机会打印错误消息(就像您看到的一样)。 该过程出现“ SIGKILL”:立即死亡。

但是...如果您查看系统日志文件,则应该看到一条消息,指出该过程已被OOM杀手杀死。

有很多资源可以解释OOM杀手::

该答案试图处理您对内存块, MALLOC_ARENA_MAX等的观察。 我不是本机内存分配器方面的专家。 这基于Glibc Wiki中的“ Malloc内部”页面。

您已阅读PrestoDB 问题8993 ,这意味着glibc malloc将为本地堆最多分配MALLOC_ARENA_MAX x NOS_THREADS个内存块。 根据“ Malloc内部原理”,这不一定是正确的。

  1. 如果应用程序请求足够大的节点,则实现将直接调用mmap ,而不是使用竞技场。 (阈值由M_MMAP_THRESHOLD选项指定。)

  2. 如果现有的竞技场已满并且压缩失败,则实现将尝试通过调用sbrkmmap来扩展竞技场。

这些因素意味着MALLOC_ARENA_MAX不会限制mmap块的数量。


请注意,arenas的目的是在有许多调用mallocfree的线程时减少争用。 但是随之而来的风险是,由于碎片,更多的内存将丢失。 MALLOC_ARENA_MAX调整的目标是减少内存碎片。

到目前为止,您还没有向我们显示任何清楚的证据表明您的内存问题是由于碎片引起的。 其他可能的解释是:

  • 您的应用程序存在本机内存泄漏,或者
  • 您的应用程序仅使用大量本机内存。

无论哪种方式,看起来MALLOC_ARENA_MAX调整都没有帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM