227 java jvm thread-dump heap-dump
我有一个Java应用程序,我从控制台运行,然后控制台执行另一个Java进程.我想获得该子进程的线程/堆转储.
在Unix上,我可以做一个kill -3 <pid>但是在Windows AFAIK上获取线程转储的唯一方法是在控制台中使用Ctrl-Break.但这只会让我转移父进程,而不是孩子.
有没有另一种方法来获得堆转储?
小智 370
jmap假设你知道,你可以用来获取正在运行的任何进程的转储pid.
使用任务管理器或资源监视器来获取pid.然后
jmap -dump:format=b,file=cheap.hprof <pid>
获取该进程的堆.
Der*_*rek 114
您混淆了两个不同的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/
ank*_*kon 19
除了使用上面提到的jconsole/visualvm之外,您还可以jstack -l <vm-id>在另一个命令行窗口中使用,并捕获该输出.
可以使用任务管理器(它是windows和unix上的进程ID)或使用来找到<vm-id> jps.
两者jstack并jps有包括6和更高太阳的JDK版本.
Law*_*Dol 16
我推荐使用JDK(jvisualvm.exe)分发的Java VisualVM.它可以动态连接并访问线程和堆.我发现一些问题非常宝贵.
Rav*_*abu 15
请尝试以下选项之一.
对于32位JVM:
jmap -dump:format=b,file=<heap_dump_filename> <pid>
对于64位JVM(明确引用):
jmap -J-d64 -dump:format=b,file=<heap_dump_filename> <pid>
对于VM参数中具有G1GC算法的64位JVM(仅使用G1GC算法生成活动对象堆):
jmap -J-d64 -dump:live,format=b,file=<heap_dump_filename> <pid>
相关的SE问题:使用jmap命令的Java堆转储错误:过早的EOF
看看各种选项jmap,在此文章
Atu*_*man 14
如果你在服务器jre 8及以上,你可以使用这个:
jcmd PID GC.heap_dump /tmp/dump
以下脚本使用 PsExec 连接到另一个 Windows 会话,因此即使通过远程桌面服务连接也能正常工作。
我为 Java 8(使用PsExec和jcmd)编写了一个名为 的小批量脚本jvmdump.bat,它转储线程、堆、系统属性和 JVM 参数。
:: set the paths for your environment
set PsExec=C:\Apps\SysInternals\PsExec.exe
set JAVA_HOME=C:\Apps\Java\jdk1.8.0_121
set DUMP_DIR=C:\temp
@echo off
set PID=%1
if "%PID%"=="" (
    echo usage: jvmdump.bat {pid}
    exit /b
)
for /f "tokens=2,3,4 delims=/ " %%f in ('date /t') do set timestamp_d=%%h%%g%%f
for /f "tokens=1,2 delims=: " %%f in ('time /t') do set timestamp_t=%%f%%g
set timestamp=%timestamp_d%%timestamp_t%
echo datetime is: %timestamp%
echo ### Version >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
%PsExec% -s %JAVA_HOME%\bin\jcmd.exe %PID% VM.version >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
echo. >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
echo ### Uptime >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
%PsExec% -s %JAVA_HOME%\bin\jcmd.exe %PID% VM.uptime >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
echo. >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
echo ### Command >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
%PsExec% -s %JAVA_HOME%\bin\jcmd.exe %PID% VM.command_line >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
echo. >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
echo ### Flags >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
%PsExec% -s %JAVA_HOME%\bin\jcmd.exe %PID% VM.flags >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
echo. >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
echo ### Properties >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
%PsExec% -s %JAVA_HOME%\bin\jcmd.exe %PID% VM.system_properties >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
%PsExec% -s %JAVA_HOME%\bin\jcmd.exe %PID% Thread.print -l >"%DUMP_DIR%\%PID%-%timestamp%-threads.log"
%PsExec% -s %JAVA_HOME%\bin\jcmd.exe %PID% GC.heap_dump "%DUMP_DIR%\%PID%-%timestamp%-heap.hprof"
echo Dumped to %DUMP_DIR%
它必须在启动 JVM 的用户的同一个 Windows 会话中运行,因此如果您通过远程桌面连接,您可能需要在其中启动命令提示符Session 0并从那里运行它。例如
%PsExec% -s -h -d -i 0 cmd.exe
这将提示您(单击底部的任务栏图标)进入View the message交互式会话,这将带您进入另一个会话中的新控制台,您可以从中运行jvmdump.bat脚本。
| 归档时间: | 
 | 
| 查看次数: | 479324 次 | 
| 最近记录: |