首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Linux系统:OOM相关问题定位及排查

Linux系统:OOM相关问题定位及排查

原创
作者头像
Janesong
修改2025-06-05 16:42:35
修改2025-06-05 16:42:35
1.1K0
举报

近日被问到OOM内存溢出、内存泄漏如何定位,现将过往相关知识点梳理总结如下:

内存溢出

OOM 定义

内存溢出(Out Of Memory,简称OOM)是指应用系统中存在无法回收的内存或使用的内存过多,最终使得程序运行要用到的内存大于能提供的最大内存

补充

  • OOM指的是内存溢出(Out Of Memory)‌,而不是内存泄漏。
  • 如果程序持续运行且内存泄漏未得到修复,最终可能会导致内存溢出。

内存溢出的常见原因及措施

常见原因

‌ 1、分配的太少‌:系统或JVM分配的内存不足以满足程序的需求。

‌ 2、用的太多‌:程序请求的内存过多,超出了系统或JVM的限制。

‌ 3、用完没释放‌:内存使用完毕后未及时释放,导致内存泄漏,最终引发内存溢出。

为了解决内存溢出问题,可以采取以下措施:

‌ 1、增加内存‌:通过增加系统内存或调整JVM的堆大小来提供更多的内存空间。

‌ 2、优化代码‌:审查并优化代码,确保及时释放不再使用的对象和资源,避免内存泄漏。

‌ 3、使用合适的数据结构‌:选择合适的数据结构来存储和处理数据,以减少内存占用。

‌ 4、监控内存使用情况‌:使用监控工具定期检查程序的内存使用情况,及时发现并处理内存泄漏和内存溢出问题。

常见的OOM问题定位分析

上述偏于理论了,来看下实战操作:本文适用 Linux系统

借助系统命令查看系统负载

可以使用命令如top查看系统负载,包括内存使用情况、进程占用资源情况等。这些信息可以帮助您了解系统的整体性能状况,以及是否有其他进程占用了大量内存。

命令行:直接敲命令【】内的命令

【top】 // 可以查看到整机的 CPU、memory情况,也可看到 占用资源最多的进程是哪个

【ps -aux | grep redis】 ===》 获取本机所有和Redis相关的进程信息

【ps -aux | grep java】 ===》获取所有 java进程的 Pid,等同于【jps】假设本次查看的是Pid为7545

【top -Hp 7545】 ===》查看 详细的 该进程下的 多个线程的情况,以及哪个线程占用CPU及memory情况. 必要的时候会借助【pstree -s #PID】用树状来分析进程父子关系等

【free memory -g 】 ===》查看整台机器当前内存使用情况、剩余内存情况

借助系统命令查看系统日志

借助下述命令,查找是否有内存不足的相关信息,包括不限于OOM问题发生的上下文和可能的原因。

【tail -fn 1000 /var/log/messages】 // 查看系统日志最后的1000行日志

【 dmesg 】 // 查看内核日志

【 grep -inr /var/log | grep -i error 】

补充:这些命令 一般 需要懂系统内核

另外,有时候 内存溢出会产生 coreDump文件,查看该文件,也能分析出一二。但一般严谨的公司,对与生产环境会关闭core文件的产生,此时在研发新版本的时候,可以自定义信号处理函数来保存crash时刻对应的函数调用堆栈信息,以替代默认的coreDump行为。

查看应用程序日志

查看应用程序的日志文件,寻找内存不足的提示信息。这些信息通常包含有关OOM问题的详细信息,如错误类型、错误发生的位置等。

这个 就需要熟悉代码,以及 拿着当时 捕获到的信息,去看当时的链路以及各个堆栈、线程都在做什么。再结合stroy场景,就最大可能复现 当时发生问题,从而 "精确修改",也方便后续回归验证。

使用工具检测内存溢出

借助工具如valgrind、memcheck等对应用程序进行内存溢出检测。

有关工具使用,可以度娘一把。

说明:上述方法:有一定局限性,对于一些大厂 生产环境的日志、coreDump文件等受限权限等,不见得能看到。只能借助平台工具去追踪,此时对业务、代码 甚至服务端服务器规格配置都要较为熟悉,才能更快更好的分析出原因。

在我过往的工作中,可以基于实际发生的时间点当时的版本,调用链,机器情况等等多方面分析,必要时可能 借助 git diff版本差异 来比较。

内存泄漏

Memory Leak 定义

内存泄漏(Memory Leak)是指程序中已动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。也可以理解为指程序在运行时未能释放不再需要的内存,导致可用内存逐渐减少。

内存泄漏与内存溢出区别

内存溢出与内存泄漏有本质的区别。内存泄漏是指程序在运行时未能释放不再需要的内存,导致可用内存逐渐减少。如果程序持续运行且内存泄漏未得到修复,最终可能会导致内存溢出。内存溢出发生在应用程序请求的内存超出系统或Java虚拟机(JVM)所能提供的最大内存空间时。此时,程序可能无法继续运行,系统会提示内存溢出错误,甚至可能导致程序崩溃或设备卡死。

内测泄漏常见错误

内存泄漏的常见错误可以归纳为以下几个方面:

1、动态分配内存后未手动释放。这是导致内存泄漏最常见的情况。当开发人员使用new(在C++中)或malloc(在C中)等操作符为对象或数据结构在堆上分配内存后,他们必须在不再需要这块内存时使用delete或free函数来手动释放它。如果忘记释放,就会导致内存泄漏。

2、指针重新赋值。在某些情况下,程序员可能会重新给指针赋值,从而使其之前指向的内存区域变为无法访问的“孤立内存”。例如,如果先为指针p分配了内存,然后又将p指向另一个新分配的内存区域,而没有释放之前p指向的内存,就会导致内存泄漏。

3、错误的内存释放。在处理结构体或包含指向动态分配内存的指针的复杂数据结构时,如果仅释放了结构体的主内存区域而没有遍历并释放其内部的动态内存,也会导致内存泄漏。

4、返回值的不正确处理。如果一个函数返回一个指向动态分配内存的指针或引用,并且这个指针或引用在函数外部没有得到正确的处理(例如,没有被释放或重新赋值),那么也会导致内存泄漏。

5、缓存泄漏。当对象引用被放入缓存中时,如果缓存没有得到正确的管理(例如,没有合适的清除策略或缓存大小限制),就可能导致内存泄漏。一旦对象被放入缓存,它们就可能长时间驻留在内存中,即使它们不再需要。

6、异常处理不当。当程序发生异常时,可能会遗漏对已分配的内存进行释放的操作。这通常发生在异常路径上的代码没有得到适当的错误处理或资源清理。

7、对象生命周期管理不当。在使用智能指针(如C++中的std::unique_ptr、std::shared_ptr)或垃圾回收机制的语言中,如果没有正确管理对象的生命周期(例如,创建了循环引用或错误地删除了对象的引用),也可能导致内存泄漏。

内存泄漏常见定位

上述内存溢出定位的手段也在一些场景下也适用于内存泄漏问题的排查。

使用工具检测内存泄漏

为了预防和检测内存泄漏,开发人员可以使用内存分析工具(如Valgrind、VisualVM、MAT等)来监控内存使用情况并定位潜在的泄漏点。Valgrind对内存泄漏检测 它算是"专家"了,但前提你得熟悉它哟。

其他实战补充

对于Redis这种内存软件,有时候定位这类问题 就需要“人肉搜索”,比如导出文件,排序看内存哪块不对劲,将可打印的东西分析+猜测,(加桩获取更多信息),尝试修改代码,再次验证,这种反复知道问题真的解决,才算是分析到位。

此外,良好的编程习惯、适当的异常处理和资源清理策略也是减少内存泄漏风险的关键。比如:在平时预计异常的时候,做return之前,提前释放。

除此之外,我们以前有个项目,因为“紧急”(这行业的人都懂哈),但有天竟然触发内存报警了,才注意到该组件内存一直在增长。运维简要分析后,将该组件重启,并反馈到研发团队。此时,我写了一个 简单的shell(收集该内存情况),放到线上作为定时任务(每小时收集一次)。观察一周后,用收集到的数据情况【总计涨幅、内存增长步长等,配套的CPU占用情况】去和研发对话。【补充:对于大公司的生产环境,不是什么工具都能上,它设计到"合规"问题,只能用最小的“资源代价”方式去获取最有用的】。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 内存溢出
    • OOM 定义
    • 内存溢出的常见原因及措施
    • 常见的OOM问题定位分析
      • 借助系统命令查看系统负载
      • 借助系统命令查看系统日志
      • 查看应用程序日志
  • 内存泄漏
    • Memory Leak 定义
    • 内存泄漏与内存溢出区别
    • 内测泄漏常见错误
    • 内存泄漏常见定位
      • 使用工具检测内存泄漏
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档