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

2022-09-02 01:22:54

我有几个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。

如果 \tmp 文件夹不存在,则不会创建它,也不会创建堆转储。

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

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

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


答案 1

命令行不会为您提供比您已经发现的内容更多的灵活性。也就是说,您可以:-XX:HeapDumpPath

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

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

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

就是这样。除了确定路径是否为目录之外,不会解析路径。

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

如果您只需要日期才能删除旧文件,则可以根据文件的上次修改时间将其删除(Unix / Linux实用程序可以帮助您)。名称中不需要包含日期。find

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

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


答案 2

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);

推荐