Java线程转储是JVM中所有活动线程的列表。
Java线程转储
Java线程转储在分析应用程序中的瓶颈和死锁情况方面非常有帮助。在这里,我们将学习通过多种方式为Java程序生成线程转储。这些说明适用于*nix操作系统,但在Windows中,步骤可能会有些不同。
- VisualVM Profiler:如果您正在分析应用程序的运行缓慢,您必须使用分析器。我们可以使用VisualVM分析器轻松为任何进程生成线程转储。您只需右键单击运行中的进程,然后单击“Thread Dump”选项即可生成它。
- jstack:Java带有jstack工具,通过它我们可以为Java进程生成线程转储。这是一个两步过程。
- 使用
ps -eaf | grep java
命令查找Java进程的PID - 以
jstack PID
运行jstack工具,将线程转储输出到控制台,您可以使用命令“jstack PID >> mydumps.tdump
”将线程转储输出附加到文件
- 使用
- 我们可以使用
kill -3 PID
命令生成线程转储。这与其他生成线程转储的方式略有不同。当发出kill命令时,线程转储会生成到程序的System out中。因此,如果是一个将控制台作为系统输出的java程序,线程转储将被打印到控制台上。如果java程序是一个Tomcat服务器,系统输出是catalina.out
,那么线程转储将生成在文件中。 - Java 8引入了
jcmd
实用程序。如果您使用的是Java 8或更高版本,则应使用此实用程序,而不是jstack。使用jcmd生成线程转储的命令是jcmd PID Thread.print
。
以上是在java中生成线程转储的四种不同方式。通常我更喜欢使用jstack或jcmd命令生成线程转储并进行分析。请注意,无论您选择哪种方式,线程转储始终相同。
Java线程转储示例
在我的上一篇文章中,我解释了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
线程转储是所有线程的列表,每个条目显示关于线程的信息,包括以下按顺序出现的内容:
- 线程名称:线程的名称
- 线程优先级:线程的优先级
- 线程ID:表示线程的唯一ID
- 线程状态:提供当前的线程状态,例如RUNNABLE、WAITING、BLOCKED。在分析死锁时,要查找被阻塞的线程以及它们试图获取锁的资源。
- 线程调用堆栈:为线程提供关键的堆栈信息。这是我们可以看到线程获取的锁以及是否正在等待任何锁的地方。
以上就是Java中的线程转储。
Source:
https://www.digitalocean.com/community/tutorials/java-thread-dump-visualvm-jstack-kill-3-jcmd