超快速定位OOM(内存溢出问题)

看完这篇文章,大家能获得的知识:

1、什么是OOM

2、为什么会发生OOM

3、哪些区域会发生OOM

4、JVM进程挂了,会有哪些可能性

5、生产环境的JVM无响应了,如何快速定位问题

6、子牙老师给你的一些成熟的调优建议

1. 什么是OOM

OOM是Out Of Memory的缩写。即内存溢出。

2. 为什么会发生OOM

如果面试官问这个问题,我知道每个人都能说一大堆,但是我希望大家就回答下面三句话,言简意赅:

  1. 业务正常运行起来就需要比较多的内存,而给JVM设置的内存过小。具体表现就是程序跑不起来,或者跑一会就挂了。

  2. GC回收内存的速度赶不上程序运行消耗内存的速度。出现这种情况一般就是往list、map中填充大量数据,内存紧张时JVM拆东墙补西墙补不过来了。所以查询记得分页啊!不需要的字段,尤其是数据量大的字段,就不要返回了!比如文章的内容。

  3. 存在内存泄漏情况,久而久之也会造成OOM。哪些情况会造成内存泄漏呢?比如打开文件不释放、创建网络连接不关闭、不再使用的对象未断开引用关系、使用静态变量持有大对象引用……

3. 哪些区域会发生OOM

JVM运行时数据区五个区域中,除了程序计数器不会发生OOM,其他区域都有可能。

除了元空间、本地方法栈、虚拟机栈、堆外,还有一块区域大家容易忽略,即直接内存

不知道什么是直接内存?看这张图

模拟这五个区域的OOM,可能有些小伙伴不知道程序怎么写,我已经给大家写好测好了,后台回复领取:OOM

可能有些小伙伴又要说了:搞挂JVM,我有无数的办法,可怎么让它一直活着或活得更久更好呢?之前写过调优相关的文章 传送门

4. JVM挂了有哪些可能性

从Windows系统角度说,JVM进程如果不是你手动关闭的,那就是OOM导致的。但是在Linux下就不一定了,因为Linux系统有一种保护机制:OOM Killer。这个机制如果展开来说又能说一堆,这里我就大概说下吧,这个机制是Unix内核独有的,它的出现是为了保证系统在可用内存较少的情况下依旧能够运行,会选择杀掉一些分值较高的进程来回收内存。这个分值是Unix内核根据一些参数动态计算出来的,当然,我们也可以改变,感兴趣的小伙伴百度学习吧。作为Java程序员,了解到这个程度基本够用了,再底层的话,很多面试官也不知道,也不会问。

除了OOM Killer,剩下的就是OOM导致JVM进程挂了。

5. 生产环境如何快速定位问题

如果面试官问你这个问题;如果你们公司的生产环境出现过这样的问题;如果你想解决却束手无策……照着这个流程去说去做即可。

前面说了,算上直接内存,共有五个区域会发生OOM:直接内存、元空间、本地方法栈、虚拟机栈、堆。

本地方法栈与虚拟机栈的OOM咱们可以不用管,为什么呢?因为这两个区域的OOM你在开发阶段或在测试阶段就能发现。GET到了吗?小伙伴们。所以这两个区域的OOM是不会生成dump文件的。

好,开始正题。如果生产环境JVM挂了,这时候不要慌,有节奏的来分析来排除。首先排除是不是被Linux杀死了,怎么看呢?通过命令[sudo egrep -i -r 'Out Of' /var/log]查看,如果是,关闭一些服务,或者把一些服务移走,腾出点内存。

如果不是,这时候就可以确定是OOM导致的,那具体是哪个OOM导致的呢?看有没有生成dump文件。如果生成了,要么是堆OOM,要么是元空间OOM;如果没生成,直接可以确定是直接内存导致的OOM。怎么解决呢?调优呗。

我这边是生成了的,所以需要进一步排查,是堆OOM还是元空间OOM。这时候需要把dump文件从服务器上下载下来,用visualvm分析。当前其他工具如MAT、JProfiler都可以,我习惯用visualvm。很多小伙伴不会看dump日志哈,子牙老师教给你诀窍,学会了,受益无穷。

如果你发现发生OOM的位置是创建对象,调用构造方法之类的代码,那一定是堆OOM。<init>就是构造方法的字节码格式。所以学点JVM底层知识还是有必要的啊。

如果你发现发生OOM的位置是类加载器那些方法,那一定是元空间OOM。

怎么样,学会了吗?

如果发生OOM让JVM自动dump内存的设置你没开,那你可以跑路了,老板正在赶来的路上,手上拿着大刀!

为了让大家更好的理解,我画成了流程图。后台回复领取:OOM

6. 一些成熟的建议

接下来才是重点,我来给你一些实战经验,让你在面试中或工作中更加自信:

  1. 调优参数务必加上-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=,发生OOM让JVM自动dump出内存,方便后续分析问题解决问题

  2. 堆内存不要设置的特别大,因为你设置的特别大,发生OOM时生成的dump文件就特别大,不好分析。建议不超过8G。

  3. 想主动dump出JVM的内存,有挺多方式,但不管哪种方式,主动dump内存会引发STW,请择时操作。即通过arthas提供的命令heapdump主动dump出JVM的内存,这个操作会引发FGC,背后是STW,操作时请选择好时机,不然老板可能提刀来见。

  4. 我提供的代码务必拉下来跑跑,找下感觉。最好是自己也去写一份与我提供的不同的,加深理解,加深印象。

转载:超快速定位OOM,值得收藏 

  • 5
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
当出现OOM(Out of Memory)内存溢出错误时,可以采取以下步骤来进行分析: 1. 查看错误日志:首先,检查应用程序或服务器的错误日志,查找与内存溢出相关的错误消息。错误消息通常会提供一些有关问题的线索。 2. 检查内存使用情况:使用监控工具(如JConsole、VisualVM等)来监视应用程序的内存使用情况。观察内存使用量是否持续增长,以及峰值内存使用量是否接近系统可用内存。 3. 内存分析工具:使用内存分析工具(如Eclipse Memory Analyzer、Java VisualVM等)来分析堆内存中的对象分布和引用关系。这些工具可以帮助你找到内存泄漏或者过多使用内存的地方。 4. 堆转储文件分析:如果应用程序发生了OOM错误并生成了堆转储文件(heap dump),可以使用堆转储文件分析工具进行分析。这些工具可以帮助你找到导致内存溢出的对象和其引用链。 5. 代码审查:仔细检查应用程序的代码,特别是与内存管理相关的部分。检查是否有不必要的对象创建、未及时释放的资源、循环引用等问题。 6. 调整JVM参数:根据应用程序的需求和硬件资源,适当调整JVM的堆内存大小(-Xmx和-Xms参数)、垃圾回收器算法(-XX:+UseParallelGC、-XX:+UseConcMarkSweepGC等)等参数。 通过以上步骤,你应该能够定位并解决OOM内存溢出问题。但请注意,内存溢出的原因可能有多种,需要根据具体情况进行分析和解决。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值