如何可靠地采取Java堆转储?

尝试进行OutOfMemoryErrors触发的堆转储时,我的团队遇到了困难。 出于具体原因,我们正在使用从bash脚本调用的jmap转储,而不是使用HeapDumpOnOutOfMemoryError标志。 我们使用64位1.6 JVM,堆大小约为3 GB。 我们的堆转储失败了90%(猜测)。

有什么我们可以做的,以提高我们得到一个干净的堆转储,我们可以用来解决内存问题的几率? 我已经读过,jmap在Java 1.4中存在重大问题,但现在应该主要解决这些问题。

    你的操作系统是哪个? (我不能添加评论)。

    对于Solaris,我们得到更好的结果,首先强制核心转储( gcore <pid> ),然后将jmap附加到核心转储文件( jmap -heap:format=b <path to java bin> <path to core>

    gcore是一个* nix工具来生成正在运行的程序的图像。 请参阅链接 。

    我们有一个JSP查询ManagementFactory.getThreadMXBean()并生成一个报告。 当应用程序崩溃时可能没什么用处,但如果您每分钟轮询一次,就会知道发生了什么。

    更多信息在这里。

    你可以通过jmx从外部监视你的应用程序。 当您知道一些指示即将到来的OutOfMemory的指标时,可以在引发exception之前触发jmap运行。

    感谢大家的build议。

    我们最终做的是编写一个脚本来主动监视垃圾收集日志。 根据我们的经验,背靠背Full GC几乎总是在OOM之前,所以我们的脚本检测到这个事件,从负载均衡池中正常地移除服务器,并强制堆转储。 这大大提高了我们的效率。

    这是一个相当古老的问题,但我会回答,希望有人可能会觉得这有用。

    jmap有一个-F选项(强制)。 这对我来说已经certificate不是那么好。 如果您要使用-F选项,我build议您也将java.io.tmp目录指定为jmap命令的一部分。 JVM版本1.6.22出现问题,由于临时目录设置,jmap实用程序无法正常工作。

    你也可以尝试通过gdb进行核心转储。 一旦你有核心,jmap可以将核心转换成堆转储。