jcmd创建的堆转储文件在哪里?

Rob*_*een 2 java hprof jcmd

我尝试使用 jcmd(从 gi​​t bash 控制台窗口)进行堆转储:

$ /c/Program\ Files/Java/jdk1.8.0_202/bin/jcmd 25156 GC.heap_dump filename=livetest-grindtohalt.hprof
25156:
Heap dump file created
Run Code Online (Sandbox Code Playgroud)

但是,该文件似乎不存在:

$ find -name livetest-grindtohalt.hprof

$
Run Code Online (Sandbox Code Playgroud)

我在哪里可以找到它?

小智 13

我在 Windows 中遇到了同样的问题。

jcmd 6232 GC.heap_dump filename=IShp1.hprof
Run Code Online (Sandbox Code Playgroud)

它运行了,说文件已创建,但搜索 c 驱动器找不到它。重新运行并得到“文件存在”。

尝试使用文件名中指定的路径和不同的文件名,

jcmd 6232 GC.heap_dump filename=c:\temp\IShp2.hprof
Run Code Online (Sandbox Code Playgroud)

这也得到了“文件存在”。

我的结论是“文件名”没有得到尊重。据推测,当指定了“文件名”时,jcmd 正在将一些内部指定的未知文件名写入某个未知位置。

反而

jcmd 6232 GC.heap_dump c:\temp\isHpdmp1.hprof
Run Code Online (Sandbox Code Playgroud)

工作并将文件写入指定位置。所以大概是为了*nix类似的东西

jcmd 6232 GC.heap_dump /opt/temp/myHd.hprof 
Run Code Online (Sandbox Code Playgroud)

  • 这个答案是纯金的。事实上,“filename=”是一个文档错误。当您指定时,jcmd 将创建名为“filename”的转储文件,这就是后续调用产生“文件存在”错误的原因(因为等号及其后面的所有内容都将被忽略)。正确的调用是直接给出所需的目标路径/名称,而不带 filename= 部分。 (2认同)

小智 11

Douglas Kretzmann 的答案为您指明了实际使用 jcmd 的正确道路。为了回答原始帖子中的问题,将根据指定 java 进程的当前工作目录解析相对路径。所以之后

jcmd 6232 GC.heap_dump heap.hprof
Run Code Online (Sandbox Code Playgroud)

您将能够heap.hprof在目录输出中找到

lsof -p 6232 | grep cwd
Run Code Online (Sandbox Code Playgroud)


gav*_*koa 6

从字面上看,上游四年来拒绝“修复”诊断:

https://bugs.openjdk.java.net/browse/JDK-8177763 - 通过 jcmd 获取 hprof 转储可以受益于更强大的选项检查。

官方文档:https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/memleaks004.html提供了不正确的示例,例如:

示例 3-2 使用 jcmd 创建堆转储

jcmd <process id/main class> GC.heap_dump filename=Myheapdump
Run Code Online (Sandbox Code Playgroud)

就脱吧filename=

转储的当前工作目录是PIDprocess 的,而不是jcmd! 因此,如果您不想搜索转储,请使用完整路径))完整工作流程:

mkdir dest/
chmod a+w dest/

sudo jcmd
1234 my.evil.app

sudo -u myuser -g mygrp jcmd 1234 GC.heap_dump $PWD/dest/myapp.hprof
Run Code Online (Sandbox Code Playgroud)