Post

一招定位JAVA_OOM中的大对象

java开发中,最令人憎恨的便是跑着跑着出现OOM

内存溢出对于新手来说最为头痛,隐蔽且难以排查。

对于正常应用来说500MB内存足够了,出现OOM一般是内存中持有太多不可释放对象,主要排查以下几点:

  1. list 或者 MAP 装太多,而且不释放,较多存在于静态引用中
  2. 数据库或者读文件一次读取太多了,比如20W行数据库记录一下加载到内存中, 较多存在于没有limit参数,或者统计sql
  3. threadlocal,StringBuffer, ByteBuffer等

内存泄漏的一般伴随着如下现象:

  • OOM伴随着疯狂的fullgc. 一般1-3S一次
  • cpu的异常增高,100%, 200%, 此时主要是JVM疯狂做无效full gc 导致
  • 服务假死,不可访问,重启服务后恢复正常。由于GC造成的Stopwrold导致

那么这种问题如何排查呢,这里介绍一个通用的流程:

  1. oom后导出内存镜像,使用命令为jmap -dump:format=b,file=文件名.hprof <进程ID>
  2. 使用JAVA_Memory_Analyzer_Tool 进行分析。

工具分析操作步骤如下:

  1. 打开内存镜像文件File->open file
  2. 点击按钮,分析对象 image
  3. 点击按包名分组排序,即可 image

图片中,Objects代表对象在内存中的数量。

上面的操作将会将内存的所有对象按照包名分组并排好序, 接着只需去查看自己业务包下面哪个对象最多,再分析其存在是否合理,基本就能排查出问题所在了。

附: oom一般是出现问题后手动导出,但是更为推荐的是在java启动中增加参数,出现oom时JVM将会自动到处镜像。方便排查。

This post is licensed under CC BY 4.0 by the author.