如何快速定位OOM问题

OOM的原因

一次性申请过多的对象

更改申请对象的数量。(分页)


内存资源耗尽 未释放

找到未释放的对象进行释放。


本身资源不够

查看堆信息:

JDK 8: jmap -heap [pid]

JDK 11往后:jhsdb jmap --heap --pid [pid]

image-20231024141116327

通过dump定位

系统已经OOM挂掉了

  1. 提前设置-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=[指定的存放路径]

    需要保证服务器的硬盘空间够大,因为该设置会记录系统在整个运行过程中所有的对象信息,占用空间。

    发生OOM后,会生成java_pidxxxxx.hprof的heap dump文件。

  2. 使用JProfiler进行查看

    image-20231024162807712
  3. 找到与业务相关的类 - 右键,使用选定对象

    image-20231024163513439
  4. 选择 传入引用,确定。

    image-20231024163605325
  5. 显示到GC根(GC Root)的路径,确定

    image-20231024163702041
  6. 根据显示的线程堆栈,查看代码进行分析。

    image-20231024163834286

系统运行中,还未OOM

方式一 导出dump文件

jmap -dump:format=b,file=[outputFileName.hprof] [pid]

在系统运行阶段导出dump文件,会造成一次FullGC、STW(Stop The World,所有线程中断)。但不导出dump文件的话,时间成本要增高很多


方式二 Arthas