Java线程转储(Thread dump)是JVM中运行中的所有线程的列表。
Java Thread Dump
Java线程转储十分有助于分析应用程序的瓶颈和死锁情况。
在这里,我们将学习多种方法来为java程序生成线程转储。这些说明适用于类unix操作系统,但在Windows中,步骤可能略有不同。
VisualVM Profiler:如果要分析应用程序的缓慢原因,则必须使用分析器。我们可以非常轻松地使用VisualVM分析器为任何进程生成线程转储。您只需右键单击正在运行的进程并单击“Thread Dump”选项即可生成它。
jstack:Java附带了jstack工具,通过它我们可以为java进程生成线程转储。过程分为以下两步。
- 使用
ps -eaf | grep java
命令找出java进程的PID - 运行jstack工具
jstack PID
以生成线程转储输出到控制台,您可以使用命令jstack PID >> mydumps.tdump
将线程转储输出附加到文件
- 使用
我们可以使用
kill -3 PID
命令来生成线程转储。这与生成线程转储的其他方式略有不同。执行kill命令时,线程转储会在程序原有的输出方式中输出。因此,如果它是系统输出方式为控制台的java程序,则线程转储将打印在控制台上。如果是系统输出方式为Tomcat服务器
catalina.out
的java程序,则将在文件中生成线程转储。Java 8引入了
jcmd
实用程序。如果您使用的是Java 8或更高版本,则应使用此代替jstack。使用jcmd生成线程转储的命令是jcmd PID Thread.print
。以上是在java中生成线程转储的四种不同方法。通常我更喜欢使用jstack或jcmd命令来生成线程转储和分析。请注意,无论您选择何种方式,线程转储(Thread dump)始终都是相同的。
Java Thread Dump示例
在我的上一篇文章中,我解释了java Timer,这里是同一个程序所生成的一个线程转储。
2012-12-26 22:28:39
Full thread dump Java HotSpot(TM) 64-Bit Server VM (23.5-b02 mixed mode):
"Attach Listener" daemon prio=5 tid=0x00007fb7d8000000 nid=0x4207 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Timer-0" daemon prio=5 tid=0x00007fb7d4867000 nid=0x5503 waiting on condition [0x00000001604d9000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at com.journaldev.threads.MyTimerTask.completeTask(MyTimerTask.java:19)
at com.journaldev.threads.MyTimerTask.run(MyTimerTask.java:12)
at java.util.TimerThread.mainLoop(Timer.java:555)
at java.util.TimerThread.run(Timer.java:505)
"Service Thread" daemon prio=5 tid=0x00007fb7d482c000 nid=0x5303 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"C2 CompilerThread1" daemon prio=5 tid=0x00007fb7d482b800 nid=0x5203 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"C2 CompilerThread0" daemon prio=5 tid=0x00007fb7d4829800 nid=0x5103 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Signal Dispatcher" daemon prio=5 tid=0x00007fb7d4828800 nid=0x5003 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Finalizer" daemon prio=5 tid=0x00007fb7d4812000 nid=0x3f03 in Object.wait() [0x000000015fd26000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x0000000140a25798> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:135)
- locked <0x0000000140a25798> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:151)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:177)
"Reference Handler" daemon prio=5 tid=0x00007fb7d4811800 nid=0x3e03 in Object.wait() [0x000000015fc23000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x0000000140a25320> (a java.lang.ref.Reference$Lock)
at java.lang.Object.wait(Object.java:503)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:133)
- locked <0x0000000140a25320> (a java.lang.ref.Reference$Lock)
"main" prio=5 tid=0x00007fb7d5000800 nid=0x1703 waiting on condition [0x0000000106116000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at com.journaldev.threads.MyTimerTask.main(MyTimerTask.java:33)
"VM Thread" prio=5 tid=0x00007fb7d480f000 nid=0x3d03 runnable
"GC task thread#0 (ParallelGC)" prio=5 tid=0x00007fb7d500d800 nid=0x3503 runnable
"GC task thread#1 (ParallelGC)" prio=5 tid=0x00007fb7d500e000 nid=0x3603 runnable
"GC task thread#2 (ParallelGC)" prio=5 tid=0x00007fb7d5800000 nid=0x3703 runnable
"GC task thread#3 (ParallelGC)" prio=5 tid=0x00007fb7d5801000 nid=0x3803 runnable
"GC task thread#4 (ParallelGC)" prio=5 tid=0x00007fb7d5801800 nid=0x3903 runnable
"GC task thread#5 (ParallelGC)" prio=5 tid=0x00007fb7d5802000 nid=0x3a03 runnable
"GC task thread#6 (ParallelGC)" prio=5 tid=0x00007fb7d5802800 nid=0x3b03 runnable
"GC task thread#7 (ParallelGC)" prio=5 tid=0x00007fb7d5803800 nid=0x3c03 runnable
"VM Periodic Task Thread" prio=5 tid=0x00007fb7d481e800 nid=0x5403 waiting on condition
JNI global references: 116
线程转储是所有线程的列表,每个条目显示有关线程的信息,其中包括下列信息。
- Thread Name:线程的名称
- Thread Priority:线程的优先级
- Thread ID:表示线程的唯一ID
- Thread Status:提供当前线程状态,例如RUNNABLE,WAITING,BLOCKED。分析死锁时,查找阻塞的线程和资源,它们尝试获取锁定。
- Thread callstack:为线程提供重要的堆栈信息。在这里我们可以看到Thread获得的锁,以及它是否在等待任何锁定。
这就是java中的线程转储。
原文地址:Java Thread Dump written by Pankaj