oom
,先说排查思路,oom
是内存溢出,则有
- 堆内存区域溢出
- 方法区或者元数据区溢出
- 非堆空间(DirectMemory)溢出
三种场景的情况。 首先通过溢出的异常报错,先确认是哪种类型。
- 如果确认是堆内存区域溢出,可能原因是内存泄露 或者堆空间回收的速度赶不上对象创建的速度,排查方案就是看gc日志,如果是gc频率很高 但是回收对象却很少 就要怀疑是内存泄露,这个时候看dump日志 找到里面占用最多的实体对象,然后再排查代码 为什么这个没回收。
如果是gc频繁,对象也能成功大量回收,但是依然溢出,说明堆空间大小跟不上业务场景的对象创建速度,要么扩大堆空间,要么优化业务场景减少这类对象的产生,为了确认是哪个对象大量产生 也需要jmap
分析dump日志找出是哪个对象,然后看代码针对性优化。 - 方法区或者元数据区溢出,可能是方法区或者元数据区过小,也可能是类过多,需要结合项目里面是否使用了会大量生成类的框架,比如说cglib asm 等,典型的就是aop框架大量生成代理, 可以使用命令
jmap –hisoty more
命令查看是哪个类最多。 - 3.直接内存溢出, 出现在使用
unsafe.allocate
直接分配内存或者项目里面使用了nio或者nio框架,排查情况比较复杂,原因也有内存泄露 代码不合理等,需要具体情况具体分析,直接内存溢出的典型特征就是dump下来的内存文件很小,但是进程占用的内存空间却很大。
利用的工具和命令有 ps 查找进程ID, jmap dump
堆内存文件和分析堆内存jstat
查看Java进程信息 包括gc 在内
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,是否有开发人员的类,也可以输出到具体文件分析
如果您喜欢此博客或发现它对您有用,则欢迎对此发表评论。 也欢迎您共享此博客,以便更多人可以参与。 如果博客中使用的图像侵犯了您的版权,请与作者联系以将其删除。 谢谢 !