Java 線程轉儲是 JVM 中所有活動線程的列表。
Java 線程轉儲
Java 線程轉儲在分析應用程序中的瓶頸和死鎖情況方面非常有幫助。在這裡,我們將學習多種生成 Java 程序的線程轉儲的方法。這些說明適用於 *nix 操作系統,但在 Windows 中,步驟可能會有所不同。
- VisualVM Profiler:如果您正在分析應用程序的速度慢問題,您必須使用分析器。我們可以使用 VisualVM 分析器輕鬆生成任何進程的線程轉儲。您只需右鍵單擊運行中的進程,然後單擊“線程轉儲”選項即可生成它。
- jstack:Java 自帶了jstack工具,通過它我們可以生成 Java 進程的線程轉儲。這是一個兩步驟的過程。
- 使用
ps -eaf | grep java
命令找出 Java 進程的 PID - 運行 jstack 工具,命令為
jstack PID
,將線程轉儲輸出到控制台,您可以使用命令“jstack PID >> mydumps.tdump
”將線程轉儲輸出附加到文件
- 使用
- 我們可以使用
kill -3 PID
命令生成線程轉儲。這與其他生成線程轉儲的方式略有不同。當發出 kill 命令時,線程轉儲將生成到程序的系統輸出。因此,如果它是一個將控制台作為系統輸出的 Java 程序,則線程轉儲將被打印在控制台上。如果 Java 程序是一個系統輸出為catalina.out
的 Tomcat 服務器,則線程轉儲將生成在文件中。 - 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