如何在Windows上获取未在控制台中运行的Java进程的线程和堆转储

问题

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

在Unix上,我可以做akill -3 <pid>但是在Windows AFAIK上获取线程转储的唯一方法是在控制台中使用Ctrl-Break。但这只会让我转移父进程,而不是孩子。

是否有另一种方法来获得堆转储?


#1 热门回答(326 赞)

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

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

jmap -dump:format=b,file=cheap.bin <pid>

获取该进程的堆。


#2 热门回答(98 赞)

你混淆了两个不同的java转储.kill -3生成一个线程转储,而不是一个堆转储。

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

要在Windows上进行线程转储,CTRL BREAK如果你的JVM是前台进程是最简单的方法。如果你在像Cygwin或MobaXterm这样的Windows上有类似unix的shell,你可以像在Unix中一样使用2146767290。

要在Unix中进行线程转储,只要为JVM获得正确的PID,CTRL Cif你的JVM就是前台进程orkill -3 {pid}会工作。

在任何一个平台上,Java都有几个可以提供帮助的实用程序。对于线程转储,jstack {pid}是你最好的选择.http://docs.oracle.com/javase/1.5.0/docs/tooldocs/share/jstack.html

只是为了完成转储问题:堆转储不常用,因为它们很难解释。但是,如果你知道在哪里/如何看待它们,它们中有很多有用的信息。最常见的用法是查找内存泄漏。最好在java命令行中设置-D,以便在OutOfMemoryError上自动生成堆转储,但也可以手动触发堆转储。最常见的方法是使用java utilityjmap

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

一个示例命令行看起来像

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

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


#3 热门回答(24 赞)

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