可能であれば、これを Solaris ボックスで実行することをお勧めします。Solaris ボックスがない場合は、Open Solaris を実行する仮想マシンをセットアップすることを検討してください。
Solaris はprstatというツールを提供しています
Prstat は、ほとんどの人がよく知っている top と同じように機能します。重要な違いは、prstat がプロセスを分割し、プロセス内の各スレッドを表示できることです。
あなたの場合、使用法は prstat -L 0 1 になります
スレッド ダンプ (スクリプトでこれを行うことをお勧めします) と組み合わせると、LWPID を照合して、CPU を占有しているスレッドを正確に見つけることができます。
これが機能的な例です(私は poc のために大きなループに入る小さなアプリを作成しました)
Standard Top は次のようなものを表示します
PID USERNAME NLWP PRI NICE SIZE RES STATE TIME CPU COMMAND
924 username 10 59 0 31M 11M run 0:53 36.02% java
次にprstatを使用して次のコマンドを使用しました
prstat -L 0 1 | grep java > /export/home/username/Desktop/output.txt
そしてprstatからの出力
PID USERNAME SIZE RSS STATE PRI NICE TIME CPU PROCESS/LWPID
924 username 31M 10M run 30 0 0:00:09 35% java/10
924 username 31M 10M sleep 59 0 0:00:00 0.8% java/3
924 username 31M 10M sleep 59 0 0:00:00 0.6% java/2
924 username 31M 10M sleep 59 0 0:00:00 0.3% java/1
これは上とあまり変わらないように見えるかもしれませんが、データの右側を見ると、PROCESS/LWPID は、CPU を消費している Java プロセス内の正確なスレッドを示しています。軽量プロセス ID (lwpid) 10 で実行されているスレッドは、CPU の 35% を消費しています。前述したように、これをスレッド ダンプと組み合わせると、正確なスレッドを見つけることができます。私の場合、これはスレッド ダンプの関連部分です。
"Thread-0" prio=3 tid=0x08173800 nid=0xa runnable [0xc60fc000..0xc60fcae0]
java.lang.Thread.State: RUNNABLE
at java.util.Random.next(Random.java:139)
at java.util.Random.nextInt(Random.java:189)
at ConsumerThread.run(ConsumerThread.java:13)
スレッドの一番上の行で、nidを LWPID に一致させることができます。nid=0xa (16進数から10進数に換算すると10)
prstat コマンドとスレッド ダンプ コマンドをスクリプトに入れ、CPU 使用率が高いときに 4 ~ 5 回実行すると、パターンが見え始め、CPU 使用率が高い原因を特定できるようになります。
私はこれまで、gc の実行時間が長く、LDAP 接続の構成ミスが原因であることに気づきました。楽しむ :)