Java Thread Dump – VisualVM, jstack, kill -3, jcmd

Ein Java Thread Dump ist eine Liste aller aktiven Threads in der JVM.

Java Thread Dump

Ein Java Thread Dump ist sehr hilfreich bei der Analyse von Engpässen in der Anwendung und Deadlock Situationen. Hier lernen wir verschiedene Wege, wie wir einen Thread Dump für ein Java-Programm generieren können. Diese Anweisungen sind gültig für *nix Betriebssysteme, aber unter Windows könnten die Schritte etwas anders sein.

  1. VisualVM Profiler: Wenn Sie eine Anwendung auf Langsamkeit analysieren, müssen Sie einen Profiler verwenden. Wir können mit dem VisualVM Profiler sehr einfach einen Thread Dump für jeden Prozess generieren. Sie müssen nur mit der rechten Maustaste auf den laufenden Prozess klicken und auf die Option „Thread Dump“ klicken, um ihn zu generieren.
  2. jstack: Java wird mit dem jstack Tool geliefert, mit dem wir einen Thread Dump für einen Java-Prozess generieren können. Dies ist ein zweistufiger Prozess.
    1. Finden Sie die PID des Java-Prozesses mit dem Befehl ps -eaf | grep java heraus
    2. Führen Sie das jstack-Tool als jstack PID aus, um die Thread-Dump-Ausgabe auf die Konsole zu generieren. Sie können die Thread-Dump-Ausgabe mit dem Befehl „jstack PID >> mydumps.tdump“ an eine Datei anhängen
  3. Wir können den Befehl kill -3 PID verwenden, um den Thread-Dump zu generieren. Dies unterscheidet sich leicht von anderen Methoden zum Generieren eines Thread-Dumps. Wenn der Kill-Befehl ausgeführt wird, wird der Thread-Dump auf der Systemausgabe des Programms ausgegeben. Wenn es sich um ein Java-Programm mit der Konsole als Systemausgabe handelt, wird der Thread-Dump auf der Konsole ausgegeben. Wenn das Java-Programm ein Tomcat-Server mit der Systemausgabe als catalina.out ist, wird der Thread-Dump in die Datei generiert.
  4. Java 8 hat das Dienstprogramm jcmd eingeführt. Sie sollten dies verwenden, wenn Sie Java 8 oder höher verwenden. Der Befehl zum Generieren eines Thread-Dumps mit JCmd lautet jcmd PID Thread.print.

Das sind vier verschiedene Möglichkeiten, einen Thread-Dump in Java zu generieren. Normalerweise bevorzuge ich den JStack- oder JCmd-Befehl, um den Thread-Dump zu generieren und zu analysieren. Beachten Sie, dass der Thread-Dump auf jede gewählte Art immer gleich bleibt.

Beispiel für Java-Thread-Dump

In meinem letzten Beitrag habe ich über Java Timer erklärt. Hier ist ein für dasselbe Programm generierter Thread-Dump.

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

Ein Thread-Dump ist die Liste aller Threads. Jeder Eintrag zeigt Informationen über den Thread an, einschließlich der folgenden in der Reihenfolge ihres Erscheinens.

  1. Thread Name: Name des Threads
  2. Thread-Priorität: Priorität des Threads
  3. Thread-ID: Stellt die eindeutige ID des Threads dar
  4. Thread-Status: Bietet den aktuellen Thread-Zustand, zum Beispiel AUSFÜHRBAR, WARTEND, BLOCKIERT. Beim Analysieren einer Deadlock-Situation sucht man nach den blockierten Threads und den Ressourcen, auf die sie versuchen, eine Sperre zu erhalten.
  5. Thread-Aufrufstapel: Bietet wichtige Stapelinformationen für den Thread. Hier sehen wir, welche Sperren vom Thread erlangt wurden und ob er auf eine Sperre wartet.

Das ist alles zum Thread-Dump in Java.

Source:
https://www.digitalocean.com/community/tutorials/java-thread-dump-visualvm-jstack-kill-3-jcmd