JAVA应用OOM OutOfMemoryError排查方法分享
本地IDE场景
如果OOM能在本地IDE复现,那对于调试来说是再方便不过了.
- 添加jvm参数,帮助排查问题
# 限制内存不要给太大,使得有问题的代码容易暴露并调试。
# HeapDumpOnOutOfMemoryError的意义为发生oom的时候,导出一份堆内存的快照。根据快照可以还原oom发生时的内存场景,从而定位问题代码。
-Xmx200m -Xms10m -XX:NativeMemoryTracking=detail -XX:+HeapDumpOnOutOfMemoryError
-
启动应用程序.
-
启动visualvm,从visualvm中选择业务应用程序.
-
在visualvm中可以很方便地看到应用程序的一些状态,如JVM配置,监控台,GC情况
- 在监控台中观察内存变化,同时调用接口,如果调用某接口时内存变化很大,很可能就是有问题的接口
-
也可以在sample中,查看具体的对象信息,从而定位问题代码
分析方法:
一般看占用最大size的对象是哪个,然后逐层追查它的reference,然后排查是哪个地方的代码出现了问题.
输出快照
-
如果还是找不到问题代码,使用终极方法,debug模式一步步排查.开启debug后,在代码打多个断点.由于进入断点时监控台会阻塞,但GC页面是不阻塞的,所以可以通过一步步走断点,同时观察GC情况,进一步缩小问题范围.
线上场景
线上场景容易复现,但不容易排查,可以参考以下思路。但还是尽可能想办法在本地复现,这样修复后也能方便地进行验证
- 添加jvm参数,帮助排查问题
# 限制内存不要给太大,使得有问题的代码容易暴露并调试。
# HeapDumpOnOutOfMemoryError的意义为发生oom的时候,导出一份堆内存的快照。根据快照可以还原oom发生时的内存场景,从而定位问题代码。
-Xmx200m -Xms10m -XX:NativeMemoryTracking=detail -XX:+HeapDumpOnOutOfMemoryError
- 启动应用程序,并调用接口想办法使其再次出现oom异常
- oom异常发生时,会在应用程序启动的工作目录(就是你执行java -jar时所在的目录)生成一份快照文件,格式如: java_pid26828.hprof
- 下载工具分析快照,如visualvm.
- 分析快照文件
- 分析可能存在问题的代码