我的团队在尝试处理由 OutOfMemoryErrors 触发的良好堆转储时遇到了困难。出于特定原因,我们目前使用从 bash 脚本调用的 jmap 进行转储,而不是使用 HeapDumpOnOutOfMemoryError 标志。我们使用的是 64 位 1.6 JVM,堆大小约为 3 GB。我们的堆转储在 90% 的情况下都会失败(估计)。
我们可以做些什么来提高获得干净堆转储的几率,我们可以用它来解决内存问题?我读过 jmap 在 Java 1.4 中存在重大问题,但现在应该主要解决这些问题。
你的操作系统是哪个?(我不能添加评论)。
gcore <pid>
对于 Solaris,我们首先强制执行核心转储 ( ),然后将 jmap 附加到核心转储文件 (jmap -heap:format=b <path to java bin> <path to core>
) ,从而获得更好的结果gcore
是一个 *nix 实用程序,用于生成正在运行的程序的图像。见链接。我们有一个查询 ManagementFactory.getThreadMXBean() 并生成报告的 JSP。当应用程序崩溃时可能没有用,但如果您每分钟左右进行一次轮询,您就会了解正在发生的事情。
更多信息在这里。
您可以从外部通过 jmx 监控您的应用程序。当您知道一些指示即将发生 OutOfMemory 的指标时,您可以在抛出异常之前触发 jmap 运行。
感谢大家的建议。
我们最终要做的是编写一个脚本来主动监控垃圾收集日志。根据我们的经验,背靠背的 Full GC 几乎总是在 OOM 之前发生,因此我们的脚本会检测到此事件,从负载平衡池中优雅地删除服务器,并强制进行堆转储。这大大提高了我们的效率。
这是一个相当老的问题,但我会回答,希望有人会觉得这很有用。
jmap 有一个 -F 选项(强制)。事实证明,这在过去对我来说效果不佳。如果您要使用 -F 选项,我建议您还将 java.io.tmp 目录指定为 jmap 命令的一部分。JVM 版本 1.6.22 存在问题,其中 jmap 实用程序由于临时目录设置而无法正常工作。
您也可以尝试通过 gdb 进行核心转储。拥有核心后,jmap 可以将核心转换为堆转储。