我有一个从控制台运行的Java应用程序,该应用程序反过来执行另一个Java进程。我想获得该子进程的线程/堆转储。

在Unix上,我可以执行kill -3 <pid>,但在Windows AFAIK上,获得线程转储的唯一方法是在控制台中按Ctrl-Break。但这只给了我父进程的转储,而不是子进程的转储。

有其他方法来获取堆转储吗?


当前回答

除了使用上面提到的jconsole/visualvm之外,您还可以在另一个命令行窗口上使用jstack -l <vm-id>,并捕获输出。

<vm-id>可以使用任务管理器(它是windows和unix上的进程id)或使用jps找到。

jstack和jps都包含在Sun JDK版本6及更高版本中。

其他回答

试试下面的一种选择。

对于32位JVM: Jmap -dump:format=b,file=<heap_dump_filename> <pid> 64位JVM(显式引用): jmap -J-d64 -dump:format=b,file=<heap_dump_filename> <pid> 对于64位JVM,在VM参数中使用G1GC算法(仅使用G1GC算法生成活对象堆): jmap -J-d64 -dump:live,format=b,file=<heap_dump_filename> <pid>

相关SE问题:Java堆转储错误与jmap命令:过早的EOF

看看本文中jmap的各种选项

我推荐JDK附带的Java VisualVM (jvisualvm.exe)。它可以动态连接并访问线程和堆。我发现在某些问题上它是无价的。

Visualvm跟踪:

如果你不能从jvisualvm连接到你正在运行的JVM,因为你没有使用正确的JVM参数启动它(并且它在远程框上),在远程框上运行jstatd,然后,假设你有一个直接连接,在visualvm中将它添加为“远程主机”,双击主机名,该框上的所有其他JVM将神奇地显示在visualvm中。

如果你没有“直接连接”到那个盒子上的端口,你也可以通过代理来做到这一点。

一旦你可以看到你想要的进程,在jvisualvm中钻到它,并使用monitor选项卡-> "heapdump"按钮。

除了使用上面提到的jconsole/visualvm之外,您还可以在另一个命令行窗口上使用jstack -l <vm-id>,并捕获输出。

<vm-id>可以使用任务管理器(它是windows和unix上的进程id)或使用jps找到。

jstack和jps都包含在Sun JDK版本6及更高版本中。

如果你想在内存不足时进行堆转储,你可以使用-XX:-HeapDumpOnOutOfMemoryError选项启动Java

c.f. JVM选项参考页