热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

javamapfailed_java.lang.OutOfMemoryError:Mapfailed总结

常见的OOM是以下这几种:1.GCoverheadlimitexceeded2.JavaHeapSpace3.Unabletocreatenewnativethrea

常见的OOM是以下这几种:

1.GC overhead limit exceeded

2.Java Heap Space

3.Unable to create new native thread

4.PermGen Space

5.Direct buffer memory

6.request {} bytes for {}. Out of swap space?

一直自认为不会有超过这个范围的OOM类型出现,没想到最近看到了一个新的OOM的类型,而这次OOM引发了一次严重的故障,整个排查过程是内部一个同事排查的,文章也是他写的,感谢他的文章,让我也学习到了之前遗漏的一个OOM相关的知识点。

故障现象为

应用日志中发现了大量的OOM异常:

Caused by: java.lang.OutOfMemoryError: Map failed

跟踪堆栈找到抛出异常的地方是在 FileChannle#map,这个方法是创建一个内存映射文件,应用为了降低堆内存的使用,同时提高写入的效率,将一个文件分成多段,内存映射多个MappedByteBuffer进行读写操作;

跟踪fileChannle.map的方法发现最终调用的是FileChannelImpl.c里的方法;

继续跟踪这段代码,发现里面调用的mmap64这个系统函数,当mmap64返回的错误码是ENOMEM时,会向上抛出OOME,进一步查阅了GNU的手册,可以发现抛出ENOMEM错误码的解释:

1. 内存不足;

2. 地址空间不足。

而从当时的现场信息来看,这两点都不成立,当时没有新的思路,于是就先按照FileChannleImpl.unmap方法中的主动释放占用内存的方法改了下代码,改了后应用就一切正常了。

当天这个机器的JVM还crash了一次,crash日志中heap占用和物理内存都是非常正常,但日志中有个现象比较诡异: Dynamic libraries:这部分信息非常多,统计以后发现有65532条。

翻阅资料,发现这个数据来自 /proc/{pid}/maps, 这个文件展示了进程的虚拟地址空间的使用情况,这时突然想到ENOMEM中有说到进程的地址空间不足导致的,但是最后的7fff005aa000还远不到上限,而且计算虚拟内存占用也就几个G的空间。

这时想到前面提到65532这个数据,联想到了file-max,但是一查看是4889494,顺势猜想虚拟内存映射是不是也有打开上限? 不出所料果然是有限制的。

max_map_count这个参数就是允许一个进程在VMAs(虚拟内存区域)拥有最大数量,VMA是一个连续的虚拟地址空间,当进程创建一个内存映像文件时VMA的地址空间就会增加,当达到max_map_count了就是返回out of memory errors。

这个数据通过下面的命令可以查看:

cat /proc/sys/vm/max_map_count

发现应用所在的机器这个数值果然是65536,而且测试修改max_map_count后filechannel#map的个数的上限也随之变化。 所以可以确定程序OOM是由于达到了这个系统的上限,也就是ENOMEM错误码中所指的out of process address。

确定了异常的触发原因,再排查引发的原因就比较容易了,再看下FileChannleImp#map的代码,发现在map第一次出现OOM时,会显式的调用System.gc去回收,但不幸的是应用启动参数上是有-XX:+DisableExplicitGC的,所以就导致了map失败,但如果在代码里主动clean是ok的现象。

总结来说,这个异常出现的原因是:

数据量增长,导致map file个数增长,应用启动参数上有-XX:+DisableExplicitGC,导致了在map file个数到达了max_map_count后直接OOM了(这也是因为heap比较大,所以full gc触发的频率低,这个问题就特别容易暴露)。

从这个问题来看,启动参数上加-XX:+DisableExplicitGC确实还是要小心,不仅map file这里是在OOM后靠显式的去执行System.gc来回收,Direct ByteBuffer其实也是这样,而这两个场景都有可能因为java本身full gc执行不频繁,导致达到了限制条件(例如map file个数达到max_map_count,而Direct ByteBuffer达到MaxDirectMemorySize),所以在CMS GC的场景下,看来还是去掉这个参数,改为加上-XX:+ExplicitGCInvokesConcurrent这个参数更稳妥一点。

原文:http://www.cnblogs.com/jooyu/p/7466190.html



推荐阅读
  • Presto:高效即席查询引擎的深度解析与应用
    本文深入解析了Presto这一高效的即席查询引擎,详细探讨了其架构设计及其优缺点。Presto通过内存到内存的数据处理方式,显著提升了查询性能,相比传统的MapReduce查询,不仅减少了数据传输的延迟,还提高了查询的准确性和效率。然而,Presto在大规模数据处理和容错机制方面仍存在一定的局限性。本文还介绍了Presto在实际应用中的多种场景,展示了其在大数据分析领域的强大潜力。 ... [详细]
  • Java能否直接通过HTTP将字节流绕过HEAP写入SD卡? ... [详细]
  • 在CICS应用环境中,众多客户端通过网络与CICS服务器进行连接。系统管理员可以通过CICS系统交易CEMT查询当前连接的客户端信息。然而,在非客户端模式下,识别用户连接并解决信息获取错误的问题变得更为复杂。本文将探讨如何在CICS服务器端准确识别非客户端模式的用户连接,并提供有效的解决方案,以确保系统的稳定性和数据的准确性。此外,还将介绍一些常用的诊断工具和技术,帮助管理员快速定位和解决问题。 ... [详细]
  • 本指南从零开始介绍Scala编程语言的基础知识,重点讲解了Scala解释器REPL(读取-求值-打印-循环)的使用方法。REPL是Scala开发中的重要工具,能够帮助初学者快速理解和实践Scala的基本语法和特性。通过详细的示例和练习,读者将能够熟练掌握Scala的基础概念和编程技巧。 ... [详细]
  • 深入解析Struts、Spring与Hibernate三大框架的面试要点与技巧 ... [详细]
  • 使用 ListView 浏览安卓系统中的回收站文件 ... [详细]
  • 该问题可能由守护进程配置不当引起,例如未识别的JVM选项或内存分配不足。建议检查并调整JVM参数,确保为对象堆预留足够的内存空间(至少1572864KB)。此外,还可以优化应用程序的内存使用,减少不必要的内存消耗。 ... [详细]
  • Java中不同类型的常量池(字符串常量池、Class常量池和运行时常量池)的对比与关联分析
    在研究Java虚拟机的过程中,笔者发现存在多种类型的常量池,包括字符串常量池、Class常量池和运行时常量池。通过查阅CSDN、博客园等相关资料,对这些常量池的特性、用途及其相互关系进行了详细探讨。本文将深入分析这三种常量池的差异与联系,帮助读者更好地理解Java虚拟机的内部机制。 ... [详细]
  • 初探性能优化:入门指南与实践技巧
    在编程领域,常有“尚未精通编码便急于优化”的声音。为了从性能优化的角度提升代码质量,本文将带领读者初步探索性能优化的基本概念与实践技巧。即使程序看似运行良好,数据处理效率仍有待提高,通过系统学习性能优化,能够帮助开发者编写更加高效、稳定的代码。文章不仅介绍了性能优化的基础知识,还提供了实用的调优方法和工具,帮助读者在实际项目中应用这些技术。 ... [详细]
  • 本文深入解析了Elasticsearch写入与查询的底层机制。在数据写入过程中,首先会将数据暂存至内存缓冲区,在此阶段数据尚不可被搜索。同时,为了保证数据的持久性和可靠性,系统会将这些数据同步记录到事务日志(translog)中。当内存缓冲区接近满载时,系统会触发刷新操作,将缓冲区中的数据写入到磁盘上的段文件中,从而使其可被搜索。此外,文章还探讨了查询过程中涉及的索引分片、倒排索引等关键技术,为读者提供了全面的技术理解。 ... [详细]
  • 在过去,我曾使用过自建MySQL服务器中的MyISAM和InnoDB存储引擎(也曾尝试过Memory引擎)。今年初,我开始转向阿里云的关系型数据库服务,并深入研究了其高效的压缩存储引擎TokuDB。TokuDB在数据压缩和处理大规模数据集方面表现出色,显著提升了存储效率和查询性能。通过实际应用,我发现TokuDB不仅能够有效减少存储成本,还能显著提高数据处理速度,特别适用于高并发和大数据量的场景。 ... [详细]
  • 揭秘腾讯云CynosDB计算层设计优化背后的不为人知的故事与技术细节
    揭秘腾讯云CynosDB计算层设计优化背后的不为人知的故事与技术细节 ... [详细]
  • Hadoop 2.6 主要由 HDFS 和 YARN 两大部分组成,其中 YARN 包含了运行在 ResourceManager 的 JVM 中的组件以及在 NodeManager 中运行的部分。本文深入探讨了 Hadoop 2.6 日志文件的解析方法,并详细介绍了 MapReduce 日志管理的最佳实践,旨在帮助用户更好地理解和优化日志处理流程,提高系统运维效率。 ... [详细]
  • 在项目开发过程中,掌握一些关键的Linux命令至关重要。例如,使用 `Ctrl+C` 可以立即终止当前正在执行的命令;通过 `ps -ef | grep ias` 可以查看特定服务的进程信息,包括进程ID(PID)和JVM参数(如内存分配和远程连接端口);而 `netstat -apn | more` 则用于显示网络连接状态,帮助开发者监控和调试网络服务。这些命令不仅提高了开发效率,还能有效解决运行时的各种问题。 ... [详细]
  • Java服务问题快速定位与解决策略全面指南 ... [详细]
author-avatar
T-R-小孩纸
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有