Javaスレッドのダンプを取得する方法には、VisualVM、jstack、kill -3、jcmdがあります。
Javaスレッドダンプは、JVM内でアクティブなすべてのスレッドの一覧です。
Java スレッドダンプ
Javaスレッドのダンプは、アプリケーションのボトルネックやデッドロックの状況を分析するのに非常に役立ちます。ここでは、Javaプログラムのスレッドダンプを生成するための複数の方法を学びます。これらの手順は*nixオペレーティングシステムに対して有効ですが、Windowsでは少し異なるかもしれません。
-
- VisualVM プロファイラー: アプリケーションの遅延を分析する場合、プロファイラーを使用する必要があります。VisualVM プロファイラーを使用すれば、どんなプロセスでもスレッドダンプを簡単に生成することができます。実行中のプロセス上で右クリックし、「スレッドダンプ」オプションをクリックするだけで生成できます。
jstack: Java には jstack ツールが付属しており、Java プロセスのスレッドダンプを生成することができます。これは 2 ステップのプロセスです。
ps -eaf | grep java コマンドを使用して、Java プロセスの PID を取得します。
jstack PID として jstack ツールを実行し、スレッドダンプをコンソールに出力します。コマンド「jstack PID >> mydumps.tdump」を使用して、スレッドダンプの出力をファイルに追加することもできます。
スレッドダンプを生成するために kill -3 PID コマンドを使用することもできます。これは他の方法と若干異なります。kill コマンドが実行されると、スレッドダンプはプログラムのシステム出力に出力されます。そのため、システム出力がコンソールである場合は、スレッドダンプがコンソールに出力されます。もし Java プログラムがシステム出力として catalina.out を持つ Tomcat サーバーである場合は、スレッドダンプがファイルに生成されます。
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.scdev.threads.MyTimerTask.completeTask(MyTimerTask.java:19)
at com.scdev.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.scdev.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のスレッドダンプに関しては以上です。