-
Notifications
You must be signed in to change notification settings - Fork 1.3k
聊一聊 线上 oom 的排查方案?
1、通过命令查看对应的进程号 比如:jps 或者 ps -ef | grep servicemix
2、输入命令查看gc情况 命令:jstat -gcutil 进程号 刷新的毫秒数 展示的记录数 比如:jstat -gcutil 14050 1000 10 (查看进程号14050,每隔1秒获取下,展示10条记录)
3、查看具体占用情况: (1)命令: jmap -histo 进程号 | more (默认展示到控制台) (2)命令: jmap -histo 14050 | more > exceptionlog.txt (输出到当前目录的exceptionlog.txt文件) 比如:jmap -histo 14050 | more 查看具体的classname,是否有开发人员的类,也可以输出到具体文件分析
补充: oom,先说排查思路,oom是内存溢出,则有堆内存区域溢出,方法区或者元数据区溢出,非堆空间(DirectMemory)溢出 三种场景的情况。 首先通过溢出的异常报错,先确认是哪种类型。
1.如果确认是堆内存区域溢出,可能原因是内存泄露 或者堆空间回收的速度赶不上对象创建的速度,排查方案就是看gc日志,如果是gc频率很高 但是回收对象却很少 就要怀疑是内存泄露,这个时候看dump日志 找到里面占用最多的实体对象,然后再排查代码 为什么这个没回收。
如果是gc频繁,对象也能成功大量回收,但是依然溢出,说明堆空间大小跟不上业务场景的对象创建速度,要么扩大堆空间,要么优化业务场景减少这类对象的产生,为了确认是哪个对象大量产生 也需要jmap 分析dump日志找出是哪个对象,然后看代码针对性优化。
2.方法区或者元数据区溢出,可能是方法区或者元数据区过小,也可能是类过多,需要结合项目里面是否使用了会大量生成类的框架,比如说cglib asm 等,典型的就是aop框架大量生成代理, 可以使用命令 jmap –hisoty more命令查看是哪个类最多。
3.直接内存溢出, 出现在使用unsafe.allocate直接分配内存或者项目里面使用了nio或者nio框架,排查情况比较复杂,原因也有内存泄露 代码不合理等,需要具体情况具体分析,直接内存溢出的典型特征就是dump下来的内存文件很小,但是进程占用的内存空间却很大。
利用的工具和命令有 ps 查找进程ID, jmap dump堆内存文件和分析堆内存 jstat 查看Java进程信息 包括gc 在内