Javaスレッドダンプ – VisualVM、jstack、kill -3、jcmd

Javaスレッドダンプは、JVMでアクティブなすべてのスレッドのリストです。

Javaスレッドダンプ

Javaスレッドダンプは、アプリケーションのボトルネックとデッドロック状況を分析するのに非常に役立ちます。ここでは、Javaプログラムのスレッドダンプを生成するための複数の方法を学びます。これらの手順は*nixオペレーティングシステムに対して有効ですが、Windowsでは手順が若干異なる場合があります。

  1. VisualVMプロファイラ:スローネスの原因を分析する場合は、プロファイラを使用する必要があります。VisualVMプロファイラを使用して、任意のプロセスのスレッドダンプを非常に簡単に生成できます。実行中のプロセスを右クリックして、「スレッドダンプ」オプションをクリックするだけで生成できます。
  2. jstack:Javaにはjstackツールが付属しており、Javaプロセスのスレッドダンプを生成できます。これは2段階のプロセスです。
    1. ps -eaf | grep javaコマンドを使用してJavaプロセスのPIDを見つけます
    2. jstack PIDとしてjstackツールを実行して、スレッドダンプの出力をコンソールに生成します。コマンド「jstack PID >> mydumps.tdump」を使用して、スレッドダンプの出力をファイルに追加できます。
  3. スレッドダンプを生成するにはkill -3 PIDコマンドを使用できます。これはスレッドダンプを生成する他の方法とは少し異なります。killコマンドが発行されると、スレッドダンプはプログラムのシステム出力に生成されます。したがって、システム出力としてコンソールを持つJavaプログラムの場合、スレッドダンプはコンソールに出力されます。Javaプログラムがシステム出力としてcatalina.outを持つTomcatサーバーである場合、スレッドダンプはファイルに生成されます。
  4. Java 8ではjcmdユーティリティが導入されています。Java 8以降の場合は、jstackの代わりにこれを使用する必要があります。jcmdを使用してスレッドダンプを生成するコマンドはjcmd PID Thread.printです。

上記はJavaでスレッドダンプを生成するための4つの異なる方法です。通常、スレッドダンプを生成して分析するためには、jstackまたはjcmdコマンドを使用します。選択した方法に関係なく、スレッドダンプは常に同じです。

Javaスレッドダンプの例

前回の投稿で、Javaタイマーについて説明しました。同じプログラムのスレッドダンプが生成されました。

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

スレッドダンプはすべてのスレッドのリストであり、各エントリーには以下の順序で表示されるスレッドに関する情報が含まれます。

  1. スレッド名: スレッドの名前
  2. スレッド優先度: スレッドの優先度
  3. スレッドID: スレッドの固有IDを表します
  4. スレッドの状態: 現在のスレッドの状態を示します。たとえば、RUNNABLE、WAITING、BLOCKEDなどです。デッドロックを分析する際は、ブロックされているスレッドとそれらがロックを取得しようとしているリソースを探します。
  5. スレッドのコールスタック: スレッドの重要なスタック情報を提供します。ここで、スレッドが取得したロックと、待機中のロックがあるかどうかを確認できます。

これで、Javaのスレッドダンプに関するすべてです。

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