やり方
CPUの高いプロセスを探す
対象のプロセスを探す為、以下のコマンドにて一覧を表示する。
# top -Hc -n 1 -p `pgrep java`
オプション「-Hc」は、スレッド単位でCPUの降順で出力する。
オプション「-n 1」は、1回だけ表示する。
オプション「-p `pgrep java`」は、Javaのプロセス番号を設定する。
「jps」コマンドを利用して、特定しても良い。
以下の様な結果が得られる。
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
5844 tomcat 20 0 2105m 281m 12m R 99.6 15.1 0:35.87 /usr/lib/jvm/java/bin/java
5824 tomcat 20 0 2105m 281m 12m S 0.0 15.1 0:00.03 /usr/lib/jvm/java/bin/java
5828 tomcat 20 0 2105m 281m 12m S 0.0 15.1 0:04.19 /usr/lib/jvm/java/bin/java
5830 tomcat 20 0 2105m 281m 12m S 0.0 15.1 0:01.02 /usr/lib/jvm/java/bin/java
5831 tomcat 20 0 2105m 281m 12m S 0.0 15.1 0:01.27 /usr/lib/jvm/java/bin/java
5832 tomcat 20 0 2105m 281m 12m S 0.0 15.1 0:00.33 /usr/lib/jvm/java/bin/java
5833 tomcat 20 0 2105m 281m 12m S 0.0 15.1 0:00.01 /usr/lib/jvm/java/bin/java
5834 tomcat 20 0 2105m 281m 12m S 0.0 15.1 0:00.00 /usr/lib/jvm/java/bin/java
5835 tomcat 20 0 2105m 281m 12m S 0.0 15.1 0:00.01 /usr/lib/jvm/java/bin/java
5836 tomcat 20 0 2105m 281m 12m S 0.0 15.1 0:01.11 /usr/lib/jvm/java/bin/java
5837 tomcat 20 0 2105m 281m 12m S 0.0 15.1 0:01.30 /usr/lib/jvm/java/bin/java
5838 tomcat 20 0 2105m 281m 12m S 0.0 15.1 0:00.00 /usr/lib/jvm/java/bin/java
5839 tomcat 20 0 2105m 281m 12m S 0.0 15.1 0:00.17 /usr/lib/jvm/java/bin/java
5842 tomcat 20 0 2105m 281m 12m S 0.0 15.1 0:00.00 /usr/lib/jvm/java/bin/java
5845 tomcat 20 0 2105m 281m 12m S 0.0 15.1 0:00.00 /usr/lib/jvm/java/bin/java
5846 tomcat 20 0 2105m 281m 12m S 0.0 15.1 0:00.00 /usr/lib/jvm/java/bin/java
5847 tomcat 20 0 2105m 281m 12m S 0.0 15.1 0:00.00 /usr/lib/jvm/java/bin/java
5848 tomcat 20 0 2105m 281m 12m S 0.0 15.1 0:00.00 /usr/lib/jvm/java/bin/java
5849 tomcat 20 0 2105m 281m 12m S 0.0 15.1 0:00.00 /usr/lib/jvm/java/bin/java
5850 tomcat 20 0 2105m 281m 12m S 0.0 15.1 0:00.02 /usr/lib/jvm/java/bin/java
5851 tomcat 20 0 2105m 281m 12m S 0.0 15.1 0:00.03 /usr/lib/jvm/java/bin/java
以上の結果から、PID「5844」がCPUを「99.6%」使っている事がわかる。
プロセス番号を16進数にする
コマンドで求める。(手抜き)
# printf "%x\n" [PID]
# printf "%x\n" 5844
# 16d4
スレッドの一覧を取得し対象のプロセスを探す*
# jstack `pgrep java` > /tmp/jstack.log
# vi /tmp/jstack.log
スレッドの一覧から、「nid=0x[PID16進数]」を探す。
ここだと、「nid=0x16d4」が該当するスレッドとなる。
"Fuka Thread" prio=10 tid=0x00007f65e42b6800 nid=0x16d4 runnable [0x00007f65c1f55000]
java.lang.Thread.State: RUNNABLE at
sun.security.provider.SHA.implDigest(SHA.java:98) at
sun.security.provider.DigestBase.engineDigest(DigestBase.java:173) at
sun.security.provider.DigestBase.engineDigest(DigestBase.java:152) at
java.security.MessageDigest$Delegate.engineDigest(MessageDigest.java:576) at
java.security.MessageDigest.digest(MessageDigest.java:353) at
fuka.FukaListerner.run(FukaListerner.java:63) at
java.lang.Thread.run(Thread.java:745)
上記の様にスレッドが見つかる。
ここでは、「Fuka Thread」というスレッドが、
「SHA」ダイジェストの計算でCPU負荷を上げているように見える。
あとは、ソースコードを追っかけて対象箇所を探す。
補足
CentOSでyumインストールした、OpenJDK1.7+tomcatでは、
「jstack」単体だと、上手く動かなかった。
「sudo -u tomcat jstack」とユーザを指定する事で正常に動いた。