OOM的排查思路

1. 什么是OOM

程序的内存不够了,挂掉了

2. OOM的原因

oom的原因其实就一个,内存不够了,我们要细分的就是哪里的内存不够了,以及为什么内存不够了

2.1 栈溢出

少见。大部分都因为递归。

2.2 方法区溢出

方法区存的都是类装载的静态结构,那什么情况会造成这种现象呢?

  1. 如果是系统启动类加载的时候出现OOM,那说明类太多了,方法区内存不够用了,就考虑是不是加大方法区的内存或者干脆加大JVM的大小,或者反向思考,是不是类真的太多了?是否需要拆服务?
  2. 如果是运行中出现这种OOM,那说明运行的时候,可能有太多类加载进去了,没错,就是反射,或者说再偶然一点,本地环境启动时,如果热部署新增太多的类也会占用方法区内存。毕竟,不管是反射还是热部署,都是破坏了双亲委派机制。

2.3 堆溢出

其实,大部分OOM场景都是堆溢出,也就是对象满了,来不及GC,内存溢出不够分配了。
那么堆中存放的又是什么呢?当然是实例对象

  1. 可能是代码中有人写了死循环创建对象,导致一瞬间创建的对象太多了
  2. 某个对象的内存占用无限增长,发生了内存泄漏。比如某个service中使用了ThreadLocal但是事后没有remove,导致它维护的ThreadLocalMap越来越大。最终溢出。

3. 发生OOM该怎么办

如果你发现服务挂掉了,去看日志发现是OOM

  1. 首先肯定是尝试重启,并且随时观察服务运行状态。如果暂时能运行,那自然是最好的,而且会排除一些情况。
  2. 不管服务起没起来,我们都要进行最关键的一步,分析为什么会出现OOM
    拿什么分析?自然需要有日志之类的记录–这里指的就是heap dump

4. heap dump

4.1 什么是heap dump

Heap dump文件是一个二进制文件,它保存了某一时刻JVM堆中对象使用情况。Heap Dump文件是指定时刻的Java堆栈的快照,是一种镜像文件。Heap Dump一般都包含了一个堆中的Java Objects, Class等基本信息。同时,当你在执行一个转储操作时,往往会触发一次GC,所以你转储得到的文件里包含的信息通常是有效的内容(包含比较少,或没有垃圾对象了) 。我们可以这么理解:heap dump记录内存信息的,thread dump是记录CPU信息的。

4.2 怎么得到heap dump

  1. 事先开启HeadDumpOnOutOfMemoryError,这样出现OOM的时候能自动留下Dump,留好第一现场。这是最推荐的方式。
JVM的启动参数中加入如下的一些参数:
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/usr/local/oom
第一个参数意思是在OOM的时候自动dump内存快照出来,第二个参数是说把内存快照存放在哪里
  1. 手工得到heap dump,这个方式就很多了,命令或者一些第三方工具,都可以获得指定java进程的heap dump。比如jdk自带的jvisualvm.exe,这个是图形化的也不用额外下载。其他方式可以自己去,有很多。
    通过jvisualvm.exe获取heap jump.
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值