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

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

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


当前回答

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

c.f. JVM选项参考页

其他回答

你可以从Cygwin发送kill -3 <pid>。你必须使用Cygwin ps选项来查找windows进程,然后将信号发送到该进程。

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

c.f. JVM选项参考页

如何获取java应用程序的进程id ?

执行“jcmd”命令可获取java应用程序的进程id。

如何获得线程转储?

jcmd PID线程。打印>线程

参考链接

您甚至可以使用jstack来获取线程转储(jstack PID > thread.dump)。参考链接

如何获得堆转储?

使用jmap工具获取堆转储。 jmap -F -dump:live,format=b,file=heap.bin PID

PID:应用程序的进程号。参考链接

您可以使用jmap获取正在运行的任何进程的转储,假设您知道pid。

使用任务管理器或资源监视器获取pid。然后

jmap -dump:format=b,file=heap.hprof <pid>

获取该进程的堆。

对于安装了bash和pgrep并且正在运行单个Java进程的系统,请尝试:

jmap -dump:format=b,file=heap.hprof $(pgrep java)

Visualvm跟踪:

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

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

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