概要
jstackはJDKに付属するコマンドです。javaを起動してるマシンであれば特別監視ツールなんかを入れなくても簡単にプロセスの状態を取得することができます。
このツールは、コマンドラインコンソールにスレッドダンプを表示します。JavaのPIDさえわかれば使用することができる。性能が出ない時やデッドロックのような現象が発生した際はこのツールを使ってスレッドの状態を取得し調査に使うことができる。
Usage
$ jstack -l <pid>
出力結果はthread単位のスタックトレースを確認することができる。
"Thread-0" #12 prio=5 os_prio=0 cpu=0.00ms elapsed=496.25s tid=0x00007f6a741f1800 nid=0x1a5 waiting on condition [0x00007f6a17a9f000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(java.base@11.0.4/Native Method)
at Server.sleepForever(Server.java:20)
at Server.lambda$0(Server.java:9)
at Server$$Lambda$1/0x0000000840060840.run(Unknown Source)
at java.lang.Thread.run(java.base@11.0.4/Thread.java:834)
"Thread-1" #13 prio=5 os_prio=0 cpu=0.00ms elapsed=496.25s tid=0x00007f6a741f3800 nid=0x1a6 waiting on condition [0x00007f6a1798f000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(java.base@11.0.4/Native Method)
at Server.sleepForever(Server.java:20)
at Server.lambda$0(Server.java:9)
at Server$$Lambda$1/0x0000000840060840.run(Unknown Source)
at java.lang.Thread.run(java.base@11.0.4/Thread.java:834)
"Thread-2" #14 prio=5 os_prio=0 cpu=0.00ms elapsed=496.25s tid=0x00007f6a741f5000 nid=0x1a7 waiting on condition [0x00007f6a1787f000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(java.base@11.0.4/Native Method)
at Server.sleepForever(Server.java:20)
at Server.lambda$0(Server.java:9)
at Server$$Lambda$1/0x0000000840060840.run(Unknown Source)
at java.lang.Thread.run(java.base@11.0.4/Thread.java:834)
例えばjavaがマルチスレッドで動いてるケースでどこかのスレッドが特にCPU使用率やメモリをたくさん食ってるといった現象が起きた際は以下のように特定することができる。
① プロセスからリソースを食ってるプロセスを特定する。
$ top -H -b -n 1 -p ${javaのpid}
上記のコマンドからリソースを食ってるPIDを取得する
② PIDを16進数へ変換し、jstackの結果からgrep
③ nid と 16進数が一致するトレースがリソースを食ってる処理なのでそこから追っていく
といった流れで調査することが可能。