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. あなたと スレッドダンプ 2014/9/20 第八回 #渋谷java Kotaro Noguchi (@enk_enk)

  2. スレッドダンプ、 取ってますか?

  3. 僕は取ってません

  4. スレッドダンプ、 読んでますか?

  5. 僕は読んでません

  6. スレッドダンプは むずかしそう

  7. いや、 スレッドダンプは むずかしくない

  8. いや、 スレッドダンプは むずかしくない と思いたい

  9. ので

  10. あなたと スレッドダンプ スレッドダンプはこわくない

  11. スレッドダンプ とはなにか

  12. スレッドダンプとはなにか • Java のスレッドのスナップショット • 取得した瞬間、JVM 上でどのような処 理が実行されているのかを調査するこ とができる •

    各スレッドの名前、状態、スタックトレー ス等を一覧できる
  13. 何の役に立つ のか

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

    ※ • JVM 最高、C++ ではこうはいかない • スレッドダンプを読めば、プログラムが 遅い原因・フリーズした原因がわかる • かもしれない ※ JVM 自体が異常な状態にある場合は取得できないかもしれませんが、そう そうあることではない
  15. スレッドダンプは 何の役に立つのか • プログラムがクラッシュしたとき • 自動的にスレッドダンプが出力される • クラッシュの原因調査に役立つ • 少なくともどのメソッドの実行中に

    クラッシュしたかはわかる
  16. スレッドダンプは 何の役に立つのか • プログラムの動作への影響が少ない • ので、本番環境でも取得できちゃった りする

  17. スレッドダンプ はこわくない

  18. スレッドダンプの 取り方

  19. スレッドダンプの取り方 - Windows 編(コンソール) • コンソールに対して Ctrl + Break •

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

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

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

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

    • Windows 編(サービス起動)で紹介した jstack ももちろん利用可能 $ ps -ef | grep java $ kill -3 <プロセス ID>
  24. スレッドダンプの取り方 - ポイント • スレッドダンプの取得では、あいだを開け ながら何度か取得しましょう • 数秒おきとか数分おきとか、場合に応 じて •

    スレッドの状態遷移を調べることが大 事
  25. スレッドダンプ はこわくない ような気がしてきた

  26. スレッドダンプの 読み方

  27. スレッドダンプの読み方 - 組成 "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)
  28. スレッドダンプの読み方 - 組成 "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 行目は名前とか状態とか
  29. スレッドダンプの読み方 - 組成 "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) 以降はスタックトレース
  30. あれ、簡単っぽい ……?

  31. スレッドダンプの読み方 - 1 – 2 行目 “http-7399-4" daemon prio=6 tid=0x0146a400

    nid=0x29c in Object.wait() [0x2ff9f000] java.lang.Thread.State: WAITING (on object monitor) スレッド名
  32. スレッドダンプの読み方 - 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” て出る
  33. スレッドダンプの読み方 - 1 – 2 行目 “http-7399-4" daemon prio=6 tid=0x0146a400

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

    nid=0x29c in Object.wait() [0x2ff9f000] java.lang.Thread.State: WAITING (on object monitor) スレッド の状態
  37. スレッドダンプの読み方 - 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 にもとづく)
  38. スレッドダンプの読み方 - 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 にもとづく)
  39. スレッドダンプの読み方 - 1 – 2 行目 • スレッド名から、どんなスレッドかあたりがつ けられる •

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

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

    あたりまえですが……。
  42. スレッドダンプの読み方 - 1 – 2 行目 • スレッドの状態 : RUNNABLE

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

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

    • ブロックされている(ロック取得待ち) • スタックトレース中にこんなんが出ます • あ、さっきのやつと <> 内がおんなじで すね……。 - waiting to lock <0x1113d330> (a java.lang.Object)
  45. (さっきのスライド) • スレッドの状態 : RUNNABLE • 元気に実行中 • ロックを取っている場合、スタックトレース中に こんなんが出ます

    - locked <0x1113d330> (a java.lang.Object)
  46. (さっきのスライド) • スレッドの状態 : RUNNABLE • 元気に実行中 • ロックを取っている場合、スタックトレース中に こんなんが出ます

    • こいつが解放されるのを待っていたのですね。 - locked <0x1113d330> (a java.lang.Object)
  47. スレッドダンプの読み方 - 1 – 2 行目 • スレッドの状態 : WAITING

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

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

    でも丁寧に説明されています • 列挙型 Thread.State
  50. スレッドダンプの読み方 - 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 行め末尾の 情報も参考になると思います • たぶん……。
  51. スレッドダンプの読み方 - 1 – 2 行目(補足) • 今回は Java 7

    のスレッドダンプで説明した が、違う JVM だと、ちょっと様子が違う • たとえば、過去の JRockit とか……。 • でも、基本は同じ。必要なら差分だけグ グればなんとかなる(はず) • ちなみに JRockit については丁寧な解 説ページがあります • スレッド ダンプの使用
  52. スレッドダンプの読み方 - 以降の行(スタックトレース) • そのスレッドでのメソッドの呼び出しスタック が並んでいる、ただのスタックトレースです • ふつうに読んでください • ただ、こういうのが挟まってくることには

    注目 - locked <0x1113d330> (a java.lang.Object) - waiting to lock <0x1113d330> (a java.lang.Object)
  53. これで

  54. スレッドダンプ はこわくない

  55. ですね。

  56. あなたと スレッドダンプ, 今すぐ CTRL + BREAK 無料スレッドダンプの DUMP

  57. 参考文献 • プログラミング言語 Java 第 4 版 • スレッドの章があってスレッドの基礎がお さえられるのがよい

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

    EEサーバからレスポンス返らず。何から調べる? (1/2) - @IT • Java - スレッドダンプの取り方 - #侍ズム • スローダウン、ハングを一発解決! スレッドダンプは トラブルシューティングの味方 • スレッド ダンプの使用 • 列挙型 Thread.State • サービス起動で運用している場合でもスレッドダンプを取る 方法はないでしょうか? - dstnフォーラム
  59. 最後に 宣伝

  60. WE’RE HIRING!

  61. WE’RE HIRING!

  62. 株式会社アプレッソは 開発者を募集しています • Java • たまに C#、JavaScript • Java できない人でも歓迎

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

  64. 株式会社アプレッソは 開発者を募集しています • 快適です

  65. 株式会社アプレッソは 開発者を募集しています • 快適です • (色がへんなのは写真がへただからです ……) • 心おきなく Java

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

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