杀死-3以获取Java线程转储


116

我正在使用kill -3命令在UNIX中查看JVM的线程转储。但是在哪里可以找到此kill命令的输出?我搞不清楚了!!


您要杀死哪个进程?它是J2EE应用服务器吗?如果是这种情况,您应该在标准输出中找到堆栈跟踪。
Luciano Fiandesio

我正在杀死运行Java类的进程
javanerd 2011年

2
不应该在控制台上写线程转储。由于java类的控制台已将std设为标准输出
javanerd 2011年

Answers:


194

您也可以使用jstack(JDK附带)进行线程转储并将输出写入所需的任何位置。在UNIX环境中不可用吗?

jstack PID > outfile

1
是的-在时间点运行。您还可以指定-l(小写L)作为打印其他锁信息的长列表
Joshua McKinnon

2
直到由于“无法从地址推断线程类型”而使jstack命令始终失败;-(
noahlz 2013年

1
如果您看到该错误,建议与您的供应商联系。快速搜索显示,例如,RHEL中有一个关于此错误和openjdk的打开错误...
Joshua McKinnon

7
值得注意的是,jstack需要JDK。如果您在仅安装了JRE的服务器上运行应用程序,则需要寻找另一种方法来进行线程转储。
jeffkempf

1
这是如何使用jstack获取在不同用户(例如Windows服务)下运行的进程的线程转储的方法:stackoverflow.com/questions/1197912/…–
Vadzim

44

线程转储将从您在其上执行过的VM写入系统kill -3。如果要将JVM的控制台输出重定向到文件,则线程转储将在该文件中。如果JVM在打开的控制台中运行,则线程转储将显示在其控制台中。


1
有一种方法可以将JVM线程转储输出重定向到单独的文件。见我的答案。
Vadzim

32

使用LogVMOutput诊断选项,可以使用中断信号将JVM线程转储输出重定向到单独的文件:

-XX:+UnlockDiagnosticVMOptions -XX:+LogVMOutput -XX:LogFile=jvm.log

5
从技术上讲,这不会“重定向”线程转储输出。它打开了JVM登录到jvm.log(其中包括线程转储输出)的功能,但是kill -QUIT仍将转储到进程的标准输出(也是如此)。针对晦涩的JVM选项的描述进行了
投票

25

在使用Java 8时,jcmd是首选方法。

jcmd <PID> Thread.print

以下是Oracle文档的摘录:

JDK 8的发行版引入了Java Mission Control,Java Flight Recorder和jcmd实用程序,用于诊断JVM和Java应用程序的问题。建议使用最新的实用程序jcmd代替以前的jstack实用程序,以增强诊断功能并降低性能开销。

但是,随应用程序一起提供此功能可能会带来许可问题,但我不确定。


1
不幸的是jcmdcom.sun.tools.attach.AttachNotSupportedException: Insufficient memory or insufficient privileges to attach虽然jstack -F成功,但无法连接到Windows服务进程:stackoverflow.com/questions/1197912/…–
Vadzim

1
您需要在与Java进程相同的用户下运行jcmd <pid> Thread.dump,否则您的连接将被删除。参见stackoverflow.com/questions/25438983/…–
Twilite,

11

在放置JVM标准输出的位置。如果您有Tomcat服务器,则将是该catalina_(date).out文件。


8

当使用kill -3时,应该在标准输出中看到线程转储。大多数应用程序服务器将标准输出写入单独的文件。使用kill -3时,您应该在那里找到它。有多种获取线程转储的方法:

  • kill -3 <PID>:将输出提供给标准输出。
  • 如果可以访问运行服务器的控制台窗口,则可以使用Ctrl+ Break键组合在STDOUT上生成堆栈跟踪。
  • 对于热点VM,我们还可以使用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 -3 <PID>时遇到问题。它可以正常工作,但是在将线程转储写入控制台后也会杀死进程。应该这样做吗?
阿什利

@Ashley-不kill -3 <PID>应该杀死JVM。您正在查看哪种类型的Java应用程序?
slm

2

在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>

这会将您的输出/线程重定向到上述命令中指定的文件控制台。



2

如果要StandAlone Java Process的线程转储,应遵循的步骤

步骤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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.