kill -3 获取java线程转储
Posted
技术标签:
【中文标题】kill -3 获取java线程转储【英文标题】:kill -3 to get java thread dump 【发布时间】:2011-06-20 01:30:05 【问题描述】:我正在使用kill -3
命令在 unix 中查看 JVM 的线程转储。但是我在哪里可以找到这个kill
命令的输出?我迷路了!!
【问题讨论】:
你要杀死哪个进程?它是 J2EE 应用服务器吗?如果是这种情况,您应该在标准输出中找到堆栈跟踪。 我正在杀死一个运行 java 类的进程 不应该在控制台上写线程转储。因为java类有控制台作为标准输出 【参考方案1】:您也可以使用 jstack(包含在 JDK 中)进行线程转储并将输出写入您想要的任何位置。这在 unix 环境中不可用吗?
jstack PID > outfile
【讨论】:
是的 - 在它运行的时间点。您还可以为打印附加锁定信息的长列表指定 -l(小写 L) 直到 jstack 命令由于“无法从地址推断线程类型”而持续失败;-( 如果您看到该错误,建议您与供应商联系。快速搜索显示,例如,RHEL 中有一个关于此错误和 openjdk 的开放错误... 值得注意的是jstack需要JDK。如果您在仅安装了 JRE 的服务器上运行应用程序,则需要找到另一种线程转储方法。 这里是如何使用 jstack 来获取在不同用户下运行的进程的线程转储,例如 windows 服务:***.com/questions/1197912/…【参考方案2】:线程转储从您执行kill -3
的VM 写入系统。如果您将 JVM 的控制台输出重定向到文件,则线程转储将在该文件中。如果 JVM 在打开的控制台中运行,则线程转储将显示在其控制台中。
【讨论】:
有一种方法可以将 JVM 线程转储输出重定向到单独的文件。请参阅我的回答。【参考方案3】:有一种方法可以将中断信号上的 JVM 线程转储输出重定向到带有 LogVMOutput diagnostic option 的单独文件:
-XX:+UnlockDiagnosticVMOptions -XX:+LogVMOutput -XX:LogFile=jvm.log
【讨论】:
从技术上讲,这不会“重定向”线程转储输出。它打开 JVM 日志记录到 jvm.log (包括线程转储输出),但 kill -QUIT 仍将转储到进程的标准输出(以及)。赞成对晦涩的 JVM 选项的描述:)【参考方案4】:在 Java 8 中,jcmd
是首选方法。
jcmd <PID> Thread.print
下面是来自Oracle documentation的sn-p:
JDK 8 的发布引入了 Java Mission Control、Java Flight Recorder 和 jcmd 实用程序,用于诊断 JVM 和 Java 应用程序的问题。 建议使用最新的实用程序 jcmd 而不是以前的 jstack 实用程序,以增强诊断并降低性能开销。
但是,将其与应用程序一起提供可能会涉及许可问题,我不确定。
【讨论】:
不幸的是jcmd
无法使用com.sun.tools.attach.AttachNotSupportedException: Insufficient memory or insufficient privileges to attach
连接到Windows 服务进程,而jstack -F
成功:***.com/questions/1197912/…
您需要在与 java 进程相同的用户下运行 jcmd 在放置 JVM 标准输出的同一位置。如果您有 Tomcat 服务器,这将是 catalina_(date).out
文件。
【讨论】:
【参考方案6】:当使用 kill -3 时,应该会在标准输出中看到线程转储。大多数应用程序服务器将标准输出写入单独的文件。你应该在使用 kill -3 时找到它。有多种获取线程转储的方法:
kill -3 <PID>
:将输出提供给标准输出。
如果可以访问运行服务器的控制台窗口,则可以使用 Ctrl+Break 组合键在 STDOUT 上生成堆栈跟踪。
对于热点虚拟机,我们还可以使用jstack
命令生成线程转储。它是 JDK 的一部分。语法如下:
Usage:
jstack [-l] <pid> (to connect to running process)
jstack -F [-m] [-l] <pid>(to connect to a hung process)
- For JRockit JVM we can use JRCMD command which comes with JDK Syntax:
jrcmd <jrockit pid> [<command> [<arguments>]] [-l] [-f file] [-p] -h]
【讨论】:
我在使用 Kill -3kill -3 <PID>
不应该杀死 JVM。您在看什么类型的 Java 应用程序?【参考方案7】:
在 Jboss 中你可以执行以下操作
nohup $JBOSS_HOME/bin/run.sh -c yourinstancename $JBOSS_OPTS >> console-$(date +%Y%m%d).out 2>&1 < /dev/null &
kill -3 <java_pid>
这会将您的输出/线程转储重定向到上述命令中指定的文件控制台。
【讨论】:
【参考方案8】:-
查找进程 ID [PS ID]
执行 jcmd [PS ID] Thread.print
【讨论】:
【参考方案9】:如果您想要独立 Java 进程的线程转储,您应该遵循的步骤
第 1 步:获取调用 java 程序的 shell 脚本的进程 ID
linux$ ps -aef | grep "runABCD"
user1 **8535** 4369 0 Mar 25 ? 0:00 /bin/csh /home/user1/runABCD.sh
user1 17796 17372 0 08:15:41 pts/49 0:00 grep runABCD
步骤 2: 获取由 runABCD 调用的子进程 ID。使用上面的 PID 来获取孩子。
linux$ ps -aef | grep **8535**
user1 **8536** 8535 0 Mar 25 ? 126:38 /apps/java/jdk/sun4/SunOS5/1.6.0_16/bin/java -cp /home/user1/XYZServer
user1 8535 4369 0 Mar 25 ? 0:00 /bin/csh /home/user1/runABCD.sh
user1 17977 17372 0 08:15:49 pts/49 0:00 grep 8535
第 3 步: 获取特定进程的 JSTACK。获取 XYSServer 进程的进程 ID。即 8536
linux$ jstack **8536** > threadDump.log
【讨论】:
以上是关于kill -3 获取java线程转储的主要内容,如果未能解决你的问题,请参考以下文章