Java内存不足自动堆转储文件名
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/34076680/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java Out of memory automatic heap dump file name
提问by Dan M
I have several Java processes and I am trying to manage the heap dumps created when OOM error occur. When I say manage I mean
我有几个 Java 进程,我正在尝试管理发生 OOM 错误时创建的堆转储。当我说管理时,我的意思是
- name the heap dump differently, based on the originating process
- delete older heap dumps to preserve disk space
- 根据原始进程对堆转储进行不同的命名
- 删除旧的堆转储以保留磁盘空间
When dumping heap on OOM with
在 OOM 上转储堆时
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp
the JVM creates a file with the following name java_pidXXXX.hprof in the specified /tmp folder (where XXXX is the PID of the process). Is there anyway to specify a different format where the PID and DATE are used to create the file name? After googling for an hour I tried myPrefix_$, {pid}, 'date'..etc. The only two things that work are
JVM 在指定的 /tmp 文件夹(其中 XXXX 是进程的 PID)中创建一个名为 java_pidXXXX.hprof 的文件。无论如何要指定一种不同的格式,其中 PID 和 DATE 用于创建文件名?谷歌搜索一个小时后,我尝试了 myPrefix_$、{pid}、'date'.. 等。唯一有效的两件事是
- not specify the file name and you get java_pidXXXX.hprof
- specify a static file name e.g. \tmp\OOM.hprof.
- 不指定文件名,你会得到 java_pidXXXX.hprof
- 指定一个静态文件名,例如\tmp\OOM.hprof。
if the \tmp folder doesn't exist it doesn't get created, nor the heap dump gets created.
如果 \tmp 文件夹不存在,则不会创建它,也不会创建堆转储。
The one idea that could use is to add a command on OOM error
可以使用的一个想法是在 OOM 错误上添加一个命令
-XX:OnOutOfMemoryError="doSomething.sh %p"
but I was trying to avoid it as I need to deploy the "doSomething.sh"
但我试图避免它,因为我需要部署“doSomething.sh”
采纳答案by RealSkeptic
The -XX:HeapDumpPath
on the command line doesn't give you any more flexibility than what you have already discovered. That is, you can either:
在-XX:HeapDumpPath
命令行上不给你任何比你已经发现了更多的灵活性。也就是说,您可以:
- Set a directory name, and then the default name
java_pidXXX.hprof
will be created in that directory. - Set a file name, and that file will be used as-is.
- 设置一个目录名称,然后
java_pidXXX.hprof
将在该目录中创建默认名称。 - 设置文件名,该文件将按原样使用。
The relevant code in the HotSpot source is heapDumper.cpp. Reading it, it doesn't look for any "magic sequences" inside the given path:
HotSpot 源代码中的相关代码是heapDumper.cpp。阅读它,它不会在给定路径中寻找任何“魔法序列”:
- It checks whether the given path is a directory. If so, uses that as a prefix, adds a file separator, and uses the default file name which is built up of hard-coded parts using a string format which is not under your control.
- If it's not a directory, it just uses it as it is.
- If it's not the first dump in this JVM's lifetime, it also appends a sequence number.
- 它检查给定的路径是否是目录。如果是这样,请将其用作前缀,添加文件分隔符,并使用默认文件名,该文件名由使用不受您控制的字符串格式的硬编码部分组成。
- 如果它不是目录,它只是按原样使用它。
- 如果它不是此 JVM 生命周期中的第一个转储,它还会附加一个序列号。
That's it. No parsing of the path beyond determining if it's a directory or not.
就是这样。除了确定它是否是目录之外,不解析路径。
The only flexibility you can add to it is to use the shell's abilities when you construct the name on the command line. That's why you may see some examples on the web that use something like name_`date`.ext
- this is processed by the shell, which substitutes `date`
with the current date once. That is, the file name will always have the date/time when the shell processed the command and started the JVM - not the date/time when the dump was created. If that's good enough for you - you can use that. Note that nowadays it's considered more acceptable to use the syntax name_$(date).ext
.
您可以添加的唯一灵活性是在命令行上构造名称时使用 shell 的功能。这就是为什么您可能会在网络上看到一些使用类似内容的示例name_`date`.ext
- 这是由 shell 处理的,它`date`
用当前日期替换一次。也就是说,文件名将始终包含 shell 处理命令并启动 JVM 的日期/时间 - 而不是创建转储的日期/时间。如果这对您来说足够好 - 您可以使用它。请注意,现在使用语法被认为更容易接受name_$(date).ext
。
If you only need the date in order to be able to remove old files then you can remove them based on the file's last modification time (the Unix/Linux utility find
can help you with that). There is no need to have the date in the name.
如果您只需要日期以便能够删除旧文件,那么您可以根据文件的最后修改时间删除它们(Unix/Linux 实用程序find
可以帮助您)。名称中无需包含日期。
The $(date)
(or `date`
) trick doesn't help you with the PID. The shell can also substitute the current PID if you use $$
- but it's the PID of the shell that processes the command line, not the JVM process itself. However, if you start your JAVA application using shell exec
command, it receives the same process ID as the shell it originated from, so you actually can use $$
to build your filename. Remember though that nothing after exec
will be executed from your script.
该$(date)
(或`date`
)招不帮助你的PID。如果您使用,shell 也可以替换当前的 PID $$
- 但它是处理命令行的shell的 PID ,而不是 JVM 进程本身。但是,如果您使用 shellexec
命令启动 JAVA 应用程序,它会收到与它源自的 shell 相同的进程 ID,因此您实际上可以$$
用来构建文件名。请记住,之后exec
不会从您的脚本中执行任何操作。
So you may try the dynamic change of the file name which @apangin suggested in his answer. Note, though, that it will probably be a little difficult to pinpoint the time of the dump itself, as you'll want to have the file name set before the OOM actually happens.
因此,您可以尝试动态更改@apangin 在他的回答中建议的文件名。但请注意,确定转储本身的时间可能有点困难,因为您希望在 OOM 实际发生之前设置文件名。
回答by apangin
HeapDumpPath
is a manageable VM option. This means you can set it to whatever you want in runtime using JMX.
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);