こんにちは!
システム開発の現場で、本番環境のアプリケーションが急に遅延して、ユーザーから問い合わせが殺到する…そんな絶望的な状況に陥ったことはないでしょうか?
本記事では、そんな時でも冷静に対処できるよう、jstack コマンドを使ったJavaアプリケーションの遅延原因特定方法について、具体的な手順と見方を徹底解説します。
jstackとは何か?
jstack は、Java Development Kit (JDK) に標準で含まれているコマンドで、実行中のJavaプロセスのスレッドダンプ(スタックトレース)を出力するツールです。
スレッドダンプとは、その瞬間に各スレッドがどのような状態にあり、どの処理を実行しているかを示す情報です。
このスレッドダンプを分析することで、どのスレッドがボトルネックになっているのか、なぜ処理が進まないのかといった、アプリケーションの内部状態を詳細に把握することができます。
jstackを使った遅延原因の特定手順
では、実際に jstack を使って遅延原因を特定する具体的な手順を見ていきましょう。
1. 遅延しているJavaプロセスのPIDを特定する
まずは、遅延が発生しているJavaプロセスのプロセスID(PID)を特定します。ps コマンドや jps コマンドを使うのが一般的です。
# psコマンドを使用
ps aux | grep java
# jpsコマンドを使用
jps -l
jps コマンドは、実行中のJavaプロセスのみを表示してくれるので便利です。
2. jstackコマンドを実行してスレッドダンプを取得する
PIDが特定できたら、jstack コマンドを実行します。本番環境で実行する場合は、出力結果をファイルにリダイレクトしておくと後でゆっくり分析できます。
jstack <PID> > threaddump.log
jstack コマンドは、実行時にわずかなオーバーヘッドしか発生しないため、本番環境で安心して実行できます。
3. スレッドダンプを分析する
出力されたスレッドダンプには、各スレッドの情報が詳細に記載されています。
"http-nio-8080-exec-1" #10 daemon prio=5 os_prio=0 tid=0x00007f9c2c01a800 nid=0x22c2 waiting for monitor entry [0x00007f9bf4108000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.example.MyService.doSomething(MyService.java:50)
- waiting to lock <0x00000000808a54c8> (a java.lang.Object)
at com.example.MyController.handleRequest(MyController.java:30)
【見るべきポイント】
- スレッド名:
http-nio-8080-exec-1のようなスレッド名から、どの処理に関連するスレッドか推測できます。 - Thread.State: スレッドの状態を示します。
- RUNNABLE: 実行中、または実行可能状態。
- BLOCKED: 他のスレッドがロックを解放するのを待機している状態。デッドロックやロック競合の可能性が高い。
- WAITING:
Object.wait()などで、他のスレッドからの通知を待機している状態。
- スタックトレース:
at com.example.MyService.doSomething(MyService.java:50)のような行が、現在スレッドが実行しているメソッドと行数を示しています。ここから、どのコードで時間がかかっているかを特定できます。
特に BLOCKED の状態になっているスレッドが多数見られる場合は、ロック競合やデッドロックを疑いましょう。複数のスレッドダンプを一定時間おきに取得し、状態が変化しないスレッドがないか確認することも非常に有効です。
まとめ
本番環境の遅延は、システムエンジニアにとって最も緊張する瞬間のひとつです。
しかし、jstack コマンドを使いこなせば、慌てることなく冷静に原因を特定し、迅速な対応を取ることができます。
jpsやpsでJavaプロセスのPIDを特定する。jstack <PID>でスレッドダンプを取得する。- スレッドダンプの
Thread.Stateやスタックトレースからボトルネックを分析する。
これらの手順を覚えておけば、いざという時にきっとあなたの助けになるはずです!


コメント