上次给老公们说过了死循环cpu飙高的排查过程,今天就带着老公们看看堆内存溢出我们一般怎么排查的。
在排查之前,我想jvm的基础知识大家应该都是了解了的吧? 老婆我就是不了解,人家要你说给我听。行行行,诶真实拿你们没办法,那我就带大家回温一下JVM的内存模型(这玩意跟JAVA内存模型JMM可不一样,不要记错了) 今天我就直说堆,因为溢出是发送在堆中的。 JVM堆内存被分为两部分:年轻代(Young Generation)和老年代(Old Generation)。 年轻代年轻代是所有新对象产生的地方。当年轻代内存空间被用完时,就会触发垃圾回收。这个垃圾回收叫做Minor GC。 年轻代被分为3个部分——Enden区和两个Survivor区。 年轻代空间的要点:
年老代内存里包含了长期存活的对象和经过多次Minor GC后依然存活下来的对象,通常会在老年代内存被占满时进行垃圾回收。 GC种类Major GC老年代的垃圾收集叫做Major GC,Major GC通常是跟full GC是等价的,收集整个GC堆。 分代GC
Full GC定义是相对明确的,就是针对整个新生代、老生代、元空间(metaspace,java8以上版本取代perm gen)的全局范围的GC。 老公们可以从上图看到年轻代分为了一个Eden区和两个survivor区(S1,S2),survivor区同一时间只会有一个满一个空,交替的。 然后就是GC到一定的阈值到老年代,今天不讲永久代所以忽略Mataspace。 老婆:那怎么分析呢?今天我就用一个JDK自带的工具jvisualvm来给大家演示一波怎么操作的,因为这玩意谁都有,你去命令行敲一下jvisualvm就出来了(Mac是这样的,不知道Windows是怎么样子的)。 操作界面:一般什么情况可能是出现了溢出呢? 超时,不进行服务,服务挂掉,接口不在服务这样的异常问题。 那模拟也很简单,我写个循环一直往List丢数据,不使用list就能看到现象了 老公们可以看到图形化界面还是很清晰明了的,这个是Visual GC的插件 大家点击菜单栏的插件,然后安装就好了,安装完了记得点击激活。 可以看到不释放,堆空间就一直上去,直到OOM(out of memory) 这个时候我们就dump下来堆信息看看 会dump出一个这样的hprof快照文件,可以用jvisualvm本身的系统去分析,我这里推荐MAT吧,因为我习惯这个了。 MAT :下载地址 下来好了我们可以看到mat已经分析了我们的文件 你看他就是个暖男,都帮我们分析出来了一个问题,我们点进去看看 他发现了是ArrayList的问题了,我们再往下看看 看到了嘛,具体代码的位置都帮我们定位好了,那排查也就是手到擒来的事情了。 延伸点 上面我们使用工具jump了,那怎么去服务器上jump呢? jmap -dump:format=b,file=<dumpfile.hprof> <pid> 有老公可能问了,不是所有的故障当时我们都在场的,无法及时jump,那也简单
配置这玩意之后,oom的时候会自动jump的,到时候拿快照分析一波就好了。 MAT的功能还有很多的,百度谷歌太多工具文了,我就不做重复的工作了,比如还可以排查对象的强弱引用,还可以查看引用链等等。 还有个只写这么点的原因是有点晚了,顶不住了,最近不拍视频也是因为事情多了,有点小忙,希望老公们体量,对了Redis的分布式锁已经在安排的路上了。 我是敖丙,一个在互联网苟且偷生的工具人。 |
|
来自: 昵称34195792 > 《java》