Java内存不足自动堆转储文件名

时间:2015-12-03 21:39:34

标签: java jvm out-of-memory heap-dump

我有几个Java进程,我正在尝试管理发生OOM错误时创建的堆转储。当我说管理时我的意思是

  • 根据原始进程
  • 以不同方式命名堆转储
  • 删除旧堆转储以保留磁盘空间

使用

在OOM上转储堆时
 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp

JVM在指定的/ tmp文件夹中创建一个名为java_pidXXXX.hprof的文件(其中XXXX是进程的PID)。 无论如何要指定一种不同的格式,其中PID和DATE用于创建文件名? 谷歌搜索了一个小时后,我尝试了myPrefix_ $,{pid},'date'等。 唯一有效的两件事是

  1. 未指定文件名,您将获得java_pidXXXX.hprof
  2. 指定静态文件名,例如\ TMP \ OOM.hprof。
  3. 如果\ tmp文件夹不存在,则不会创建它,也不会创建堆转储。

    可以使用的一个想法是在OOM错误上添加命令

    -XX:OnOutOfMemoryError="doSomething.sh %p"
    

    但我试图避免它,因为我需要部署“doSomething.sh”

2 个答案:

答案 0 :(得分:9)

命令行上的-XX:HeapDumpPath并没有比您已经发现的更灵活。也就是说,您可以:

  • 设置目录名称,然后将在该目录中创建默认名称java_pidXXX.hprof
  • 设置文件名,该文件将按原样使用。

HotSpot源代码中的相关代码为heapDumper.cpp。阅读它,它不会寻找任何"魔术序列"在给定的路径内:

  • 检查给定路径是否为目录。如果是这样,使用它作为前缀,添加文件分隔符,并使用由不受您控制的字符串格式构成的硬编码部分的默认文件名。
  • 如果它不是目录,它只是按原样使用它。
  • 如果它不是此JVM生命周期中的第一个转储,它还会附加一个序列号。

那就是它。除了确定它是否是目录之外,不解析路径。

您可以添加的唯一灵活性是在命令行上构造名称时使用shell的功能。这就是为什么你可以在网上看到一些使用name_`date`.ext之类的例子的原因 - 这是由shell处理的,用`date`代替当前日期一次 。也就是说,文件名将始终具有shell处理命令并启动JVM的日期/时间 - 而不是创建转储的日期/时间。如果这对你来说足够好 - 你可以使用它。请注意,现在使用语法name_$(date).ext被认为更为可接受。

如果您只需要日期以便能够删除旧文件,那么您可以根据文件的最后修改时间删除它们(Unix / Linux实用程序find可以帮助您)。名称中没有日期。

$(date)(或`date`)技巧无助于您使用PID。如果使用$$,shell也可以替换当前的PID - 但它是处理命令行 shell的PID,而不是JVM进程本身。但是,如果使用shell exec命令启动JAVA应用程序,它将获得与其源自的shell相同的进程ID,因此您实际上可以使用$$来构建文件名。请记住,exec之后的任何内容都不会从您的脚本中执行。

因此,您可以尝试动态更改@apangin在其答案中建议的文件名。但请注意,确定转储本身的时间可能有点困难,因为您希望在OOM实际发生之前设置文件名。

答案 1 :(得分:8)

HeapDumpPath是一个可管理的VM选项。这意味着您可以使用JMX将其设置为运行时所需的任何内容。

    String pid = ManagementFactory.getRuntimeMXBean().getName();
    pid = pid.substring(0, pid.indexOf('@'));
    String date = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
    String fileName = "/tmp/heap_" + pid + "_" + date + ".dump";

    HotSpotDiagnosticMXBean bean = ManagementFactory.newPlatformMXBeanProxy(
            ManagementFactory.getPlatformMBeanServer(),
            "com.sun.management:type=HotSpotDiagnostic",
            HotSpotDiagnosticMXBean.class);
    bean.setVMOption("HeapDumpOnOutOfMemoryError", "true");
    bean.setVMOption("HeapDumpPath", fileName);