JavaでCPUを占有しているスレッドを探せ！

## やり方

***CPUの高いプロセスを探す***

対象のプロセスを探す為、以下のコマンドにて一覧を表示する。

```text
# top -Hc -n 1 -p `pgrep java`
```

オプション「-Hc」は、スレッド単位でCPUの降順で出力する。
オプション「-n 1」は、1回だけ表示する。
オプション「-p \`pgrep java\`」は、Javaのプロセス番号を設定する。
「jps」コマンドを利用して、特定しても良い。


以下の様な結果が得られる。

```text
   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進数にする***

コマンドで求める。（手抜き）

```text
# printf "%x\n" [PID]
```

```text
# printf "%x\n" 5844
# 16d4
```

***スレッドの一覧を取得し対象のプロセスを探す****

```text
# jstack `pgrep java` > /tmp/jstack.log
# vi /tmp/jstack.log
```

スレッドの一覧から、「nid=0x[PID16進数]」を探す。
ここだと、「nid=0x16d4」が該当するスレッドとなる。

```text
"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」とユーザを指定する事で正常に動いた。