关于HeapDumpOnOutOfMemoryError无法生成dump文件的问题
问题背景
最近公司的一个项目,因为JVM内存大小设置问题导致应用出现OOM,但看到指定的HeapDumpPath路径中没有最新的dump文件产生,导致无法定位问题。遂决定看看为什么不生成新文件。
问题复现
使用现有项目在本地环境中,设置JVM参数:-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/Users/xxx/applog/oom.hprof -Xms5m -Xmx5m。因项目是springboot框架,因此启动时迅速出现OOM异常。 第一次启动抛出异常后查看目录下确实生成了oom.hprof文件,但第二次启动后,没有再次生成最新的oom.hprof文件,也没有覆盖旧文件。
问题分析
问题的原因在于,当程序抛出OOM异常时,JVM会自动dump堆内存,由于当前指定的参数到文件名 -XX:HeapDumpPath=/Users/xxx/applog/oom.hprof 路径下存在旧的oom.hprof文件,无法生成新文件。
解决方案
方案一:指定HeapDumpPath到目录
指定HeapDumpPath到目录后,如果出现OOM异常,JVM会根据线程的pid自动生成新的dump文件,每次启动的pid不同则不会出现文件名相同无法生成dump文件的情况。
但该方案存在一个问题,假如应用使用docker或者k8s部署,则大概率会出现容器中的Java进程每次启动时的pid相同,则仍然会出现因为pid相同无法生成新dump文件的情况,因此引出方案二
方案二:使用OnOutOfMemoryError参数
使用 -XX:OnOutOfMemoryError=’/home/docker/oom-test/heapDump.sh’ 参数可以在出现OOM且生成dump文件后执行一个脚本对dump文件进行重命名,这样下次再出现OOM,就不会因为文件已存在而生成失败了。
heapDump.sh文件内容
1 | #在该脚本下修改hprof的文件名 |
效果验证
JVM根据pid生成了dumpfile,之后运行了heapDump.sh脚本重命名了dumpfile
如果您喜欢此博客或发现它对您有用,则欢迎对此发表评论。 也欢迎您共享此博客,以便更多人可以参与。 如果博客中使用的图像侵犯了您的版权,请与作者联系以将其删除。 谢谢 !