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

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

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


当前回答

如果您使用的是JDK 1.6或以上版本,您可以使用jmap命令来获取Java进程的堆转储,条件是您应该知道ProcessID。

如果你在Windows机器上,你可以使用任务管理器来获取PID。对于Linux机器,您可以使用各种命令,如ps -A | grep java或netstat -tupln | grep java或top | grep java,这取决于您的应用程序。

然后可以使用类似jmap -dump:format=b,file=sample_heap_dump的命令。hprof 1234,其中1234是PID。

有多种工具可用于解释hprof文件。我将推荐使用简单的Oracle的visualvm工具。

其他回答

您混淆了两个不同的java转储。Kill -3生成线程转储,而不是堆转储。

线程转储= JVM输出到stdout的每个线程的堆栈跟踪作为文本。 堆转储= JVM进程输出到二进制文件的内存内容。

要在Windows上进行线程转储,如果您的JVM是前台进程,CTRL+BREAK是最简单的方法。如果你在Windows上有一个类似Unix的shell,比如Cygwin或MobaXterm,你可以像在Unix中一样使用kill -3 {pid}。

要在Unix中进行线程转储,如果您的JVM是前台进程,则可以使用CTRL+C或kill -3 {pid},只要您为JVM获得正确的pid即可。

对于这两种平台,Java都提供了一些有用的实用程序。对于线程转储,jstack {pid}是最好的选择。http://docs.oracle.com/javase/1.5.0/docs/tooldocs/share/jstack.html

Just to finish the dump question out: Heap dumps are not commonly used because they are difficult to interpret. But, they have a lot of useful information in them if you know where/how to look at them. The most common usage is to locate memory leaks. It is a good practice to set the -D on the java command-line so that the heap dump is generated automatically upon an OutOfMemoryError, -XX:+HeapDumpOnOutOfMemoryError But, you can manually trigger a heap dump, also. The most common way is to use the java utility jmap.

注意:此实用程序并非在所有平台上都可用。从JDK 1.6开始,jmap可以在Windows上使用。

命令行示例如下所示

jmap -dump:file=myheap.bin {pid of the JVM}

输出“myheap.bin”不是人类可读的(对我们大多数人来说),您需要一个工具来分析它。我的首选是MAT. http://www.eclipse.org/mat/

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

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

如何获得线程转储?

jcmd PID线程。打印>线程

参考链接

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

如何获得堆转储?

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

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

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

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

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

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

我认为在Linux进程中创建.hprof文件的最好方法是使用jmap命令。例如:jmap -dump:format=b,file=filename。hprof {PID}