我有一个Java应用程序,我从控制台运行,然后控制台执行另一个Java进程.我想获得该子进程的线程/堆转储.
在Unix上,我可以做一个kill -3
但是在Windows AFAIK上获取线程转储的唯一方法是在控制台中使用Ctrl-Break.但这只会让我转移父进程,而不是孩子.
有没有另一种方法来获得堆转储?
jmap
假设你知道,你可以用来获取正在运行的任何进程的转储pid
.
使用任务管理器或资源监视器来获取pid
.然后
jmap -dump:format=b,file=cheap.hprof
获取该进程的堆.
您混淆了两个不同的Java转储. kill -3
生成线程转储,而不是堆转储.
线程转储=将JVM输出中的每个线程的堆栈跟踪作为文本输出到stdout.
堆转储= JVM进程输出到二进制文件的内存内容.
要在Windows上进行线程转储,CTRL+ BREAK如果您的JVM是前台进程是最简单的方法.如果你在Windows上有类似unix的shell,比如Cygwin或MobaXterm,kill -3 {pid}
你可以在Unix中使用.
要在Unix中进行线程转储,CTRL+ C如果您的JVM是前台进程,或者kill -3 {pid}
只要您为JVM获得正确的PID就可以工作.
无论使用哪种平台,Java都有几个可以提供帮助的实用程序.对于线程转储,jstack {pid}
是你最好的选择.http://docs.oracle.com/javase/1.5.0/docs/tooldocs/share/jstack.html
只是为了完成转储问题:堆转储不常用,因为它们很难解释.但是,如果你知道在哪里/如何看待它们,它们中有很多有用的信息.最常见的用法是查找内存泄漏.最好-D
在java命令行上设置,以便在OutOfMemoryError上自动生成堆转储,-XX:+HeapDumpOnOutOfMemoryError
但是,您也可以手动触发堆转储.最常见的方法是使用java实用程序jmap
.
注意:此实用程序并非在所有平台上都可用.从JDK 1.6开始,jmap
可在Windows上使用.
示例命令行看起来像
jmap -dump:file=myheap.bin {pid of the JVM}
输出"myheap.bin"不是人类可读的(对于我们大多数人来说),你需要一个工具来分析它.我的偏好是MAT. http://www.eclipse.org/mat/
我认为在Linux进程中创建.hprof文件的最佳方法是使用jmap命令.例如:jmap -dump:format=b,file=filename.hprof {PID}
除了使用上面提到的jconsole/visualvm之外,您还可以jstack -l
在另一个命令行窗口中使用,并捕获该输出.
可以使用任务管理器(它是windows和unix上的进程ID)或使用来找到jps
.
两者jstack
并jps
有包括6和更高太阳的JDK版本.
我推荐使用JDK(jvisualvm.exe)分发的Java VisualVM.它可以动态连接并访问线程和堆.我发现一些问题非常宝贵.
请尝试以下选项之一.
对于32位JVM:
jmap -dump:format=b,file=
对于64位JVM(明确引用):
jmap -J-d64 -dump:format=b,file=
对于VM参数中具有G1GC算法的64位JVM(仅使用G1GC算法生成活动对象堆):
jmap -J-d64 -dump:live,format=b,file=
相关的SE问题:使用jmap命令的Java堆转储错误:过早的EOF
看看各种选项jmap
,在此文章
如果你在服务器jre 8及以上,你可以使用这个:
jcmd PID GC.heap_dump /tmp/dump
如果要在内存不足的情况下使用heapdump,可以使用该选项启动Java -XX:-HeapDumpOnOutOfMemoryError
cf JVM选项参考页面
你可以kill -3
从Cygwin 发送.您必须使用Cygwin ps
选项来查找Windows进程,然后将信号发送到该进程.
您可以运行jconsole
(包含在Java 6的SDK中),然后连接到您的Java应用程序.它将向您显示每个Thread运行及其堆栈跟踪.