欢迎阅读本文,以下是使用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命令查看线程及死锁堆栈信息的实例 - Python技术站