我的团队在尝试获取由 OutOfMemoryErrors 触发的良好堆转储时遇到了困难。由于特定原因,我们目前使用从 bash 脚本调用的 jmap 来获取转储,而不是使用 HeapDumpOnOutOfMemoryError 标志。我们使用的是 64 位 1.6 JVM,堆大小约为 3 GB。我们的堆转储有 90% 的时间会失败(估计)。
我们可以做些什么来提高获得干净的堆转储的几率,以便用于解决内存问题?我了解到 jmap 在 Java 1.4 中存在重大问题,但这些问题现在应该大部分都得到了解决。
答案1
您的操作系统是什么?(我无法添加评论)。
对于 Solaris,我们首先强制核心转储(gcore <pid>
),然后将 jmap 附加到核心转储文件(jmap -heap:format=b <path to java bin> <path to core>
)可以获得更好的结果
gcore
是一个 *nix 实用程序,用于生成正在运行的程序的映像。请参阅关联。
答案2
我们有一个 JSP,它查询 ManagementFactory.getThreadMXBean() 并生成报告。当应用程序崩溃时可能没什么用,但如果你每隔一分钟左右轮询一次,你就会知道发生了什么。
答案3
您可以从外部通过 jmx 监控您的应用程序。当您知道一些表明即将出现 OutOfMemory 的指标时,您可以在引发异常之前触发 jmap 运行。
答案4
这是一个相当老的问题,但我会回答,希望有人会发现它有用。
jmap 有一个 -F 选项(强制)。过去事实证明,这个选项对我来说效果不佳。如果您要使用 -F 选项,我建议您还将 java.io.tmp 目录指定为 jmap 命令的一部分。JVM 版本 1.6.22 存在一个问题,由于临时目录设置,jmap 实用程序无法正常工作。
您还可以尝试通过 gdb 进行核心转储。一旦获得核心,jmap 就可以将核心转换为堆转储。