Upgrade to Pro — share decks privately, control downloads, hide ads and more …

あなたとスレッドダンプ - 第八回 #渋谷java

あなたとスレッドダンプ - 第八回 #渋谷java

第八回 #渋谷java で発表した「あなたとスレッドダンプ」です。
スレッドダンプの使いみち、取り方、読み方について説明しています。
スレッドダンプこわくない。

Kotaro Noguchi

September 20, 2014
Tweet

More Decks by Kotaro Noguchi

Other Decks in Programming

Transcript

  1. スレッドダンプは 何の役に立つのか • プログラムが遅いとき・フリーズしたとき • そんなときでも、スレッドダンプは取れる • プログラムが遅い・フリーズしている場 合も、JVM 自体は動作しているため

    ※ • JVM 最高、C++ ではこうはいかない • スレッドダンプを読めば、プログラムが 遅い原因・フリーズした原因がわかる • かもしれない ※ JVM 自体が異常な状態にある場合は取得できないかもしれませんが、そう そうあることではない
  2. スレッドダンプの取り方 - Windows 編(コンソール) • コンソールに対して Ctrl + Break •

    可能な場合は、起動時に出力をファイル にリダイレクトしておくと読むのが楽です • リダイレクトしていない場合は、コマンド プロンプトのプロパティで「画面のバッ ファサイズ」を大きくすること • そうしないと頭が切れます…… $ [実行ファイル] > console.log 2>&1
  3. スレッドダンプの取り方 - Windows 編(コンソール) • コンソールに対して Ctrl + Break •

    可能な場合は、起動時に出力をファイル にリダイレクトしておくと読むのが楽です • リダイレクトしていない場合は、コマンド プロンプトのプロパティで「画面のバッ ファサイズ」を大きくすること • そうしないと頭が切れます…… $ [実行ファイル] > console.log 2>&1
  4. スレッドダンプの取り方 - Windows 編(サービス起動) • jstack を使用する • まずは jps

    でプロセス ID を調べる • 対象のプロセスがわかったら $ jps $ jstack <プロセス ID> > c:¥tmp¥jstack.txt
  5. スレッドダンプの取り方 - Windows 編(サービス起動) • jstack で「プロセスにアクセスできませ ん」 • PsExec

    の出番ですね 参考 : dstnフォーラム - サービス起動で運用している場合でもスレッドダンプを取 る方法はないでしょうか? • なお jstack は JRE には含まれない (JDK に入っている)ので注意 psexec -s jstack PID > c:¥tmp¥jstack.txt
  6. スレッドダンプの取り方 - UNIX 編 • プロセス ID を調べてから kill -3

    • Windows 編(サービス起動)で紹介した jstack ももちろん利用可能 $ ps -ef | grep java $ kill -3 <プロセス ID>
  7. スレッドダンプの読み方 - 組成 "http-7399-4" daemon prio=6 tid=0x0146a400 nid=0x29c in Object.wait()

    [0x2ff9f000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x182d3880> (a org.apache.tomcat.util.net.JIoEndpoint$Worker) at java.lang.Object.wait(Object.java:485) at org.apache.tomcat.util.net.JIoEndpoint$Worker.await(JIoEndpoint.java:458) - locked <0x182d3880> (a org.apache.tomcat.util.net.JIoEndpoint$Worker) at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:484) at java.lang.Thread.run(Thread.java:662)
  8. スレッドダンプの読み方 - 組成 "http-7399-4" daemon prio=6 tid=0x0146a400 nid=0x29c in Object.wait()

    [0x2ff9f000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x182d3880> (a org.apache.tomcat.util.net.JIoEndpoint$Worker) at java.lang.Object.wait(Object.java:485) at org.apache.tomcat.util.net.JIoEndpoint$Worker.await(JIoEndpoint.java:458) - locked <0x182d3880> (a org.apache.tomcat.util.net.JIoEndpoint$Worker) at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:484) at java.lang.Thread.run(Thread.java:662) 1-2 行目は名前とか状態とか
  9. スレッドダンプの読み方 - 組成 "http-7399-4" daemon prio=6 tid=0x0146a400 nid=0x29c in Object.wait()

    [0x2ff9f000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x182d3880> (a org.apache.tomcat.util.net.JIoEndpoint$Worker) at java.lang.Object.wait(Object.java:485) at org.apache.tomcat.util.net.JIoEndpoint$Worker.await(JIoEndpoint.java:458) - locked <0x182d3880> (a org.apache.tomcat.util.net.JIoEndpoint$Worker) at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:484) at java.lang.Thread.run(Thread.java:662) 以降はスタックトレース
  10. スレッドダンプの読み方 - 1 – 2 行目 “http-7399-4" daemon prio=6 tid=0x0146a400

    nid=0x29c in Object.wait() [0x2ff9f000] java.lang.Thread.State: WAITING (on object monitor) スレッド名
  11. スレッドダンプの読み方 - 1 – 2 行目 “http-7399-4" daemon prio=6 tid=0x0146a400

    nid=0x29c in Object.wait() [0x2ff9f000] java.lang.Thread.State: WAITING (on object monitor) デーモンスレッドならここに “daemon” て出る
  12. スレッドダンプの読み方 - 1 – 2 行目 “http-7399-4" daemon prio=6 tid=0x0146a400

    nid=0x29c in Object.wait() [0x2ff9f000] java.lang.Thread.State: WAITING (on object monitor) スレッドの優先順位
  13. スレッドダンプの読み方 - 1 – 2 行目 “http-7399-4" daemon prio=6 tid=0x0146a400

    nid=0x29c in Object.wait() [0x2ff9f000] java.lang.Thread.State: WAITING (on object monitor) スレッド ID
  14. スレッドダンプの読み方 - 1 – 2 行目 “http-7399-4" daemon prio=6 tid=0x0146a400

    nid=0x29c in Object.wait() [0x2ff9f000] java.lang.Thread.State: WAITING (on object monitor) ネイティブスレッド ID
  15. スレッドダンプの読み方 - 1 – 2 行目 “http-7399-4" daemon prio=6 tid=0x0146a400

    nid=0x29c in Object.wait() [0x2ff9f000] java.lang.Thread.State: WAITING (on object monitor) スレッド の状態
  16. スレッドダンプの読み方 - 1 – 2 行目 “http-7399-4" daemon prio=6 tid=0x0146a400

    nid=0x29c in Object.wait() [0x2ff9f000] java.lang.Thread.State: WAITING (on object monitor) スレッド の状態(Thread.State にもとづく)
  17. スレッドダンプの読み方 - 1 – 2 行目 “http-7399-4" daemon prio=6 tid=0x0146a400

    nid=0x29c in Object.wait() [0x2ff9f000] java.lang.Thread.State: WAITING (on object monitor) スレッド名 • なんかむずかしそうだけど、だいたいここ見 れば十分 スレッド ID スレッド の状態(Thread.State にもとづく)
  18. スレッドダンプの読み方 - 1 – 2 行目 • スレッド名から、どんなスレッドかあたりがつ けられる •

    JVM の内部スレッドもいろいろあったり する • CompilerThread, Finalizer, Reference Handler, VM Thread…… 等 • スレッドの異様な多さに惑わされな いようにしましょう
  19. スレッドダンプの読み方 - 1 – 2 行目 • スレッド ID(tid)で、任意のスレッドの状態 を追跡できる

    • スレッドダンプを何度か取得したら、ス レッド ID をキーにしてスレッドを追跡でき る • 侍 というツールがこの方面で非常に有 用らしいです
  20. スレッドダンプの読み方 - 1 – 2 行目 • スレッドの状態 : RUNNABLE

    • 元気に実行中 • ロックを取っている場合、スタックトレース中に こんなんが出ます • ちなみにこれは RUNNABLE じゃなくても 出ます(ロックを取った状態で、別のロック を待ってるとか……ありますよね) - locked <0x1113d330> (a java.lang.Object)
  21. スレッドダンプの読み方 - 1 – 2 行目 • スレッドの状態 : BLOCKED

    • ブロックされている(ロック取得待ち) • スタックトレース中にこんなんが出ます - waiting to lock <0x1113d330> (a java.lang.Object)
  22. スレッドダンプの読み方 - 1 – 2 行目 • スレッドの状態 : BLOCKED

    • ブロックされている(ロック取得待ち) • スタックトレース中にこんなんが出ます • あ、さっきのやつと <> 内がおんなじで すね……。 - waiting to lock <0x1113d330> (a java.lang.Object)
  23. スレッドダンプの読み方 - 1 – 2 行目 • スレッドの状態 : WAITING

    • 下記いずれかの状態で待機している • Object.wait(タイムアウトなし) • Thread.join(タイムアウトなし) • LockSupport.park • たとえば、wait の場合、スタックトレース中 にこんなんが出ます - waiting on <0x0a7348d8> (a java.lang.Object)
  24. スレッドダンプの読み方 - 1 – 2 行目 • スレッドの状態 : TIMED_WAITING

    • 下記いずれかの状態で待機している • Object.wait(タイムアウトあり) • Thread.join(タイムアウトあり) • LockSupport.parkNanos • LockSupport.parkUntil • WAITING とだいたい同じですね。
  25. スレッドダンプの読み方 - 1 – 2 行目 • なお、Thread.State については Javadoc

    でも丁寧に説明されています • 列挙型 Thread.State
  26. スレッドダンプの読み方 - 1 – 2 行目 “http-7399-4” daemon prio=6 tid=0x0146a400

    nid=0x29c in Object.wait() [0x2ff9f000] java.lang.Thread.State: WAITING (on object monitor) スレッド の状態 • スレッドの状態については、1 行め末尾の 情報も参考になると思います • たぶん……。
  27. スレッドダンプの読み方 - 1 – 2 行目(補足) • 今回は Java 7

    のスレッドダンプで説明した が、違う JVM だと、ちょっと様子が違う • たとえば、過去の JRockit とか……。 • でも、基本は同じ。必要なら差分だけグ グればなんとかなる(はず) • ちなみに JRockit については丁寧な解 説ページがあります • スレッド ダンプの使用
  28. 参考文献 • プログラミング言語 Java 第 4 版 • スレッドの章があってスレッドの基礎がお さえられるのがよい

    • 増補改訂版 Java 言語で学ぶデザインパ ターン入門 マルチスレッド編 • Object.wait の少々ややこしい仕組みに ついて非常にわかりやすく解説されてい ます、WAITING がどういう状態なのか わからない方におすすめ
  29. 参考 Web ページ • jstack でスレッドダンプを取る - にょきにょきブログ • 現場にキく、Webシステムの問題解決ノウハウ(1):Java

    EEサーバからレスポンス返らず。何から調べる? (1/2) - @IT • Java - スレッドダンプの取り方 - #侍ズム • スローダウン、ハングを一発解決! スレッドダンプは トラブルシューティングの味方 • スレッド ダンプの使用 • 列挙型 Thread.State • サービス起動で運用している場合でもスレッドダンプを取る 方法はないでしょうか? - dstnフォーラム
  30. 株式会社アプレッソは 開発者を募集しています • Java • たまに C#、JavaScript • Java できない人でも歓迎

    • プログラミングできる人・できるようになれ る人なら!(ちなみに僕は 10 ヶ月前の 入社当時 Java できない人でした) • もちろん Java できる人も歓迎
  31. 株式会社アプレッソは 開発者を募集しています • 快適です • (色がへんなのは写真がへただからです ……) • 心おきなく Java

    が書けます • たのしいエンタープライズジャバ • DataSpider Servista(主力製品) • DataSpider BPM • PIMSYNC
  32. 株式会社アプレッソは 開発者を募集しています • Wantedly で募集してます • パッケージ開発エンジニア募集!SIer出 身の方大歓迎!! • パッケージ開発のエンジニアがどう働い

    ているか知りたい人、集まれ! • 個人ブログにもちょっと様子を書いています • パッケージ開発エンジニアを募集してい ます - この国では犬がコードを書いてい ます