【问题标题】:kill -3 to get java thread dumpkill -3 获取java线程转储
【发布时间】:2011-06-20 01:30:05
【问题描述】:

我正在使用kill -3 命令在 unix 中查看 JVM 的线程转储。但是我在哪里可以找到这个kill 命令的输出?我迷路了!!

【问题讨论】:

  • 你要杀死哪个进程?它是 J2EE 应用服务器吗?如果是这种情况,您应该在标准输出中找到堆栈跟踪。
  • 我正在杀死一个运行 java 类的进程
  • 不应该在控制台上写线程转储。因为java类有控制台作为标准输出

标签: java multithreading dump


【解决方案1】:

您也可以使用 jstack(包含在 JDK 中)进行线程转储并将输出写入您想要的任何位置。这在 unix 环境中不可用吗?

jstack PID > outfile

【讨论】:

  • 是的 - 在它运行的时间点。您还可以为打印附加锁定信息的长列表指定 -l(小写 L)
  • 直到 jstack 命令由于“无法从地址推断线程类型”而持续失败;-(
  • 如果您看到该错误,建议您与供应商联系。快速搜索显示,例如,RHEL 中有一个关于此错误和 openjdk 的开放错误...
  • 值得注意的是jstack需要JDK。如果您在仅安装了 JRE 的服务器上运行应用程序,则需要找到另一种线程转储方法。
  • 这里是如何使用 jstack 来获取在不同用户下运行的进程的线程转储,例如 windows 服务:stackoverflow.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 实用程序,以增强诊断并降低性能开销。

但是,将其与应用程序一起提供可能会涉及许可问题,我不确定。

【讨论】:

【解决方案5】:

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

【讨论】:

    【解决方案6】:

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

    • kill -3 &lt;PID&gt;:将输出提供给标准输出。
    • 如果可以访问运行服务器的控制台窗口,则可以使用 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 -3 时遇到问题。它工作正常,但在将线程转储写入控制台后也会终止进程。它应该这样做吗?
    • @Ashley - 不,kill -3 &lt;PID&gt; 不应该杀死 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】:
      1. 查找进程 ID [PS ID]
      2. 执行 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
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-08-15
          相关资源
          最近更新 更多