jstack+jdb命令查看线程及死锁堆栈信息的实例

欢迎阅读本文,以下是使用jstack和jdb命令查看线程及死锁堆栈信息的实例攻略。

欢迎阅读本文,以下是使用jstack和jdb命令查看线程及死锁堆栈信息的实例攻略。

1.什么是jstack和jdb

jstack是Java开发工具包(JDK)中的一个命令行工具,可以用于在运行时查看Java虚拟机中各个线程的状态、堆栈信息以及死锁等信息。

jdb也是JDK中的一个命令行工具,是Java Debugger的缩写,可以在运行时通过命令行调试Java应用程序。

2.如何使用jstack和jdb查看线程及死锁堆栈信息

2.1.查看线程状态和堆栈信息

假设我们有一个Java应用程序正在运行,我们要查看当前Java虚拟机中的线程状态和堆栈信息。我们可以使用以下命令:

jstack <pid>

其中< pid>是Java进程的进程ID,可以使用以下任意一种方式获取到:

  • 在命令行使用jps命令,例如:jps -l,可以查看所有Java进程的进程ID和类的完整名字;
  • 在Java应用程序中使用ManagementFactory.getRuntimeMXBean().getName()方法获取当前进程的名称,再使用String.split()方法获取进程ID。

例如,我们有一个正在运行的Java程序,进程ID为1234,我们可以使用以下命令查看线程状态和堆栈信息:

jstack 1234

执行该命令后,jstack将打印出所有Java线程的状态和堆栈信息,例如:

"Thread1" #1 prio=5 os_prio=0 tid=0x00007f1c28002000 nid=0x7531 waiting on condition [0x00007f1c9bdfd000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
        at java.lang.Thread.sleep(Native Method)
        at TestThread.run(TestThread.java:15)

"Thread2" #2 prio=5 os_prio=0 tid=0x00007f1c28002800 nid=0x7532 waiting on condition [0x00007f1c9bced000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
        at java.lang.Thread.sleep(Native Method)
        at TestThread.run(TestThread.java:15)

"main" #3 prio=5 os_prio=0 tid=0x00007f1c2862a000 nid=0x752b runnable [0x00007f1c9beee000]
   java.lang.Thread.State: RUNNABLE
        at TestThread.run(TestThread.java:21)
        at java.lang.Thread.run(Thread.java:748)

这里我们可以看到三个线程的信息,其中Thread1和Thread2都处于TIMED_WAITING状态,main线程处于RUNNABLE状态。在堆栈信息中,我们还可以看到TestThread类中run()方法的调用信息。

2.2.查看死锁

假设我们想要查找Java应用程序中的死锁,我们可以使用以下命令:

jstack -F <pid> | grep '\- locked'

其中< pid>是进程ID。-F参数表示强制转储所有线程的堆栈信息,即使它们未响应。grep命令用于过滤出锁相关信息。

假设我们有一个正在运行的Java程序,进程ID为1234,我们可以使用以下命令查找死锁:

jstack -F 1234 | grep '\- locked'

如果有死锁存在,该命令将输出类似以下内容的信息:

Found one Java-level deadlock:
=============================
"Thread1":
  waiting to lock monitor 0x0000000000000001 (object 0x000000076ac715a8, a java.lang.Object),
  which is held by "Thread2"
"Thread2":
  waiting to lock monitor 0x0000000000000002 (object 0x000000076ac71620, a java.lang.Object),
  which is held by "Thread1"

这里我们可以看到Thread1和Thread2两个线程之间的死锁关系,它们都在等待一个锁,而这个锁又被它们两个持有。

2.3.使用jdb查看线程状态和堆栈信息

jdb可以通过命令行在运行时调试Java应用程序。它可以帮助我们查看线程状态和堆栈信息,用于诊断Java应用程序中的错误。

假设我们有一个正在运行的Java应用程序,我们可以使用以下命令启动jdb调试器,连接到该应用程序:

jdb -connect com.sun.jdi.SocketAttach:hostname=localhost,port=8000

其中,hostname和port参数分别是Java应用程序启动时指定的hostname和端口号,用于指定调试器连接到该应用程序。如果Java应用程序没有指定hostname和端口号,可以通过在启动时加上以下命令行参数打开调试器接口:

-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8000

其中address参数指定调试器连接的端口号。这个命令行参数可以在启动Java应用程序时使用,在IDE中设置,或在运行中使用Java虚拟机工具中的jcmd命令动态添加。

连接到Java应用程序后,我们可以使用以下命令查看线程状态和堆栈信息:

threads

此时,jdb将列出Java虚拟机中所有线程的状态和堆栈信息,例如:

Group system:
   (java.lang.Thread.State: TIMED_WAITING)
       at sun.misc.Unsafe.park(Native Method)
       at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
       at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
       at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1099)
       at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
       at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
       at java.lang.Thread.run(Thread.java:748)

Group main:
   (java.lang.Thread.State: WAITING)
       at java.lang.Object.wait(Native Method)
       - waiting on <0x000000076ada6170> (a java.lang.ref.ReferenceQueue$Lock)
       at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:144)
       - locked <0x000000076ada6170> (a java.lang.ref.ReferenceQueue$Lock)
       at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:165)
       at org.apache.kafka.clients.producer.internals.Sender.run(Sender.java:239)
       at org.apache.kafka.clients.producer.internals.Sender.run(Sender.java:162)
       at java.lang.Thread.run(Thread.java:748)

Group com.example.demo.Application.main:
   (java.lang.Thread.State: WAITING)
       at java.lang.Object.wait(Native Method)
       - waiting on <0x000000076ac5e6a8> (a java.lang.Object)
       at java.lang.Object.wait(Object.java:502)
       at org.springframework.boot.SpringApplication.run(SpringApplication.java:329)
       at org.springframework.boot.SpringApplication.run(SpringApplication.java:1258)
       at org.springframework.boot.SpringApplication.run(SpringApplication.java:1246)
       at com.example.demo.Application.main(Application.java:10)

此时我们可以看到三个不同的线程组,分别是system、main和com.example.demo.Application.main,以及每个线程的状态和堆栈信息。

3.总结

在Java应用程序开发和运维中,我们常常需要查看应用程序中的线程状态和堆栈信息,以方便诊断应用程序中的问题。jstack和jdb命令是常用的工具,可以帮助我们快速获取这些信息。在使用这两个命令时,我们需要了解它们的使用方法和常用参数,以便在需要时能够快速使用。

本文标题为:jstack+jdb命令查看线程及死锁堆栈信息的实例

基础教程推荐