Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

困らない程度のJDK入門

あまり頑張りたくない人のためのJDK入門

  • Be the first to comment

困らない程度のJDK入門

  1. 1. 困らない程度のJDK入門 Yohei Oda @ Bizreach 1
  2. 2. はじめに 2
  3. 3. 今日話す人 小田洋平 Scalaエンジニア 前職はJava系いろいろ JJUGでGCの話したり… https://www.slideshare.net/yodajp/shenandoahgc- 69803455 3
  4. 4. だいたいこんな感じですよね? JVM あんま興味ないっす → そんなに知るメリットがない → 他にもっと役に立ちそうな知識がある → 隠蔽される(実装知らなくても使える)のはよいこと 4
  5. 5. とはいえ たまーに困るときがある。 必要に応じて調べればよいが、何も知らないと調べるのがつ らい インターネットや周りの人→ 玉石混淆 5
  6. 6. 今日の勉強会(と資料)の方針 普通に使いそうな話をする あまり使いそうにないことは飛ばす 知識習得のコスパ重視 割合的に少ない事項についてはあまり触れない あまりつっこみすぎない 方向性がわかれば細かいことは調べられる 玄人なら手を出していいという類の話はしない 玄人はそもそもこの資料を読まない 6
  7. 7. コンパイラの話 7
  8. 8. コンパイラで知っておかないと困ること 8
  9. 9. コンパイラで知っておかないと困ること → たぶんそんなにない 9
  10. 10. 15年前のドキュメントを読んでみる 最適化の決定を行うためのfinal の使用は、使用すべきでないとされるCの register キーワードに非常によく似ています。register キーワードは、 オプティマイザーを助けたいというプログラマーの願望が動機となっていま すが、現実にはあまり助けにならないことがわかりました。そうでないこと を信じたいものですが、コンパイラーは通常、特に現代のRISCプロセッサー では、コードの最適化の決定において人間より優れています。事実、ほとん どのCコンパイラーは、register キーワードを完全に無視します。初期の Cコンパイラーは最適化をまったく行わなかったのでそれを無視しました。 また、現代のCコンパイラーは、それがなくてもより優れた最適化の決定を 行えるので無視します。どちらの場合も、register キーワードは、Java クラスやメソッドに適用されるfinal キーワードとよく似て、パフォーマ ンスを向上させることはほとんどありません。コードを最適化するには、 効果的なアルゴリズムを使用したり冗長な計算を行わないなどの大きな利 点をもたらす最適化のみ行い、実行サイクル数レベルの最適化はコンパイラ ーとJVMに任せましょう。 https://www.ibm.com/developerworks/jp/java/library/j-jtp1029/ より引用 10
  11. 11. トーシロが手ぇ出すな臭すごい Brian先生に従っておこう! 権威には逆らわない これで終わると怒られそうなのでちょっとだけ話を続けます 11
  12. 12. ちょっと前まで人類に残されていた仕事 JITコンパイラの選択 クライアントコンパイラ(C1) サーバコンパイラ(C2) 12
  13. 13. バイトコードからマシンコードにする方法は3つある インタプリタ C1 (-client) C2 (-server) コード生成のコスト <‐> 生成したコードのパフォーマンス 13
  14. 14. TieredCompilation JDK6 まで インタプリタ実行時にプロファイリングをして、選択したコ ンパイラで最適化する どっちのコンパイラが良いか考える余地がある JDK7 から インタプリタ、C1、C2 を動的に使い分けられるようになった C1でもプロファイリングできるようになった 4階層の最適化レベルをいったりきたりする →更に考えることが減った コンパイルのしきい値とかもうかつにいじらないほうが良か ったり… 14
  15. 15. JDKのオプションに関する余談 ON/OFF にするような設定の場合、以下のような書式になってい ます。 有効にするとき ‐XX:+<フラグ名>  無効にするとき ‐XX:‐<フラグ名>  また、バージョンや環境によってオプションのデフォルト設定が 変わることがあるので、その環境で何が設定されているかを確認 したい時があります。  ‐XX:+PrintFlagsFinal をつけるとフラグの状態を見ることができ ます。 (例) TieredCompilation のデフォルトを見たいとき > java ‐XX:+PrintFlagsFinal| grep TieredCompilation      bool TieredCompilation                         = true            15
  16. 16. 人類がちゃんとやらないといけないこと ロジックに適したアルゴリズムを使う 人類に優しい設計 パフォーマンス測定 最適化の影響を考慮する コードキャッシュ(JITコンパイラのコード置き場)が枯渇し ないようサイジングする  ‐XX:ReservedCodeCacheSize オプション 今は枯渇したら古いのを捨ててるので気づきづらい(だ からOKというわけでもない)  jconsole とかで見られる  ‐XX:+PrintCodeCacheOnCompilation というのもある (が出力量多い) 16
  17. 17. 最適化の動作をいじるとき 調査目的で最適化を無効にしたい場合  ‐Djava.compiler=none  JITコンパイラのバグを踏んでクラッシュしているのでは?と 疑わしいときの切り分け あやしいマルチスレッドアプリケーションのデバッグ メモリモデルを理解せずにマルチスレッド処理を書くと 最適化された瞬間に破綻するコードが爆誕することがあ る JIT有効化したら起きたからってすぐコンパイラのせいに するのはやめよう 特定のメソッドだけ切り替えることもできる 17
  18. 18. ガベージコレクタ 18
  19. 19. ガベージコレクタ 基本になるガベージコレクタのアルゴリズムは限られている マークスイープ マークコンパクト コピー アルゴリズムによって、長所/短所がある スループット 停止時間 並行性 オーバーヘッド 19
  20. 20. 各GCの動きの違い 別の資料で説明します… 20
  21. 21. まとめると 無駄に生存しているオブジェクトが増えるとヤングGCは遅く なる パラレルGCは停止時間が長くなるが効率は良い CMSは並行性が高いが断片化するしチューニングが難しい G1は並行性ではなくソフトリアルタイム性を重視する G1はオーバーヘッドはあるがスケーラビリティが高い 21
  22. 22. いざというときの話 22
  23. 23. いざというときの話 解析ツール 23
  24. 24. とりあえずjcmd をおぼえときましょう 昔は jstat とか jmap とか jhat とか色々使い分けていた 最近のJDKであればかなりのことが jcmd でカバーできる 昔のツール類は順次廃止になりそう 24
  25. 25. jcmd で1つだけ覚えて帰るなら… jcmd プロセスID help > jcmd 12345 help 12345: The following commands are available: GC.rotate_log Thread.print GC.class_stats GC.class_histogram GC.heap_dump VM.flags VM.system_properties help For more information about a specific command use  'help <command>'. そのプロセスに実行できるコマンドを教えてくれる 25
  26. 26. help で出てきたコマンドを打つ > jcmd 12345 Thread.print 12345: Full thread dump Java HotSpot(TM) 64‐Bit Server VM (25.112‐b16 mixed  "main" #1 prio=5 os_prio=31 tid=0x00007fa3bd000800 nid=0x1303 in    java.lang.Thread.State: WAITING (on object monitor)         at java.lang.Object.wait(Native Method)         ‐ waiting on <0x000000076e9672b0> (a java.lang.UNIXProcess         at java.lang.Object.wait(Object.java:502)         at java.lang.UNIXProcess.waitFor(UNIXProcess.java:395)         ‐ locked <0x000000076e9672b0> (a java.lang.UNIXProcess)         at  フラグ設定が必要なコマンドの場合は教えてくれます 26
  27. 27. コマンドに対してもヘルプを打つことができます > jcmd 12345 help Thread.print 12345: Thread.print Print all threads with stacktraces. Impact: Medium: Depends on the number of threads. Permission: java.lang.management.ManagementPermission(monitor) Syntax : Thread.print [options] Options: (options must be specified using the <key> or <key>=<value>         ‐l : [optional] print java.util.concurrent locks (BOOLEAN, fa  ‐l というオプションがあるので、↓が実行できることがわかります > jcmd 12345 Thread.print ‐l 27
  28. 28. ちなみによく使うのは↓の3つです Thread.print GC.class_histogram GC.heap_dump 28
  29. 29. Thread.print JVM のその時点のスレッドの状態を出力する ハングのときにとる 数秒おきに複数回実行し状態遷移の有無を確認するのが定石 一回だとたまたまその処理をしているのかずっとその処 理をしているのかよくわからない 複数のスレッドダンプを読み込んでグラフィカルに差分を出して くれるツールもあります 29
  30. 30. GC.class_histogram ヒープ内にどんなオブジェクトが多いかを見られる ある特定のオブジェクトが増えている疑惑があるときに定期 的に取得して比較するのにも便利 30
  31. 31.  GC.class_histogram の補足 実行すると [C というクラスがよく上の方に出てくると思うので すが、たまにこれを見て「Cヒープが増えてます!」と言う人がい ます…。 頭の [ は配列の意味で、アルファベット一文字はプリミティブ型 の略称なので、  [C は char の配列です。 ちなみにちょっとわかりづらいやつとしては、 Z が boolean で,  J は long です。 ※  B は byte で、  [L... はオブジェクトの配列 ( [Ljava.lang.Object; など)の表記で使われています。 31
  32. 32. GC.heap_dump Javaヒープのダンプ バイナリファイルなので、ツールを使って開きます  Eclipse Memory Analyzer が有名 巨大なメモリを使うインスタンスだと巨大なファイルが出ま す あるオブジェクトが何から参照されているかを調べるのに便 利 ちなみにヒープダンプは  OutOfMemoryError が起きたときに自動的 に出力するよう設定できます ‐XX:+HeapDumpOnOutOfMemoryError ‐XX:HeapDumpPath=ファイルパス 32
  33. 33. OutOfMemoryError が出ました! まずどうしますか? 33
  34. 34. OutOfMemoryError が出ました! まずどうしますか? →再起動っす… 34
  35. 35.  OutOfMemoryError は VirtualMachineError なので、動いていても ちゃんと動いていることは保証されません。さっさと再起動しま しょう。 JDK8u92 からOutOfMemoryError 発生時にJVM を停止させ るオプションがついた(  ‐XX:+ExitOnOutOfMemoryError ) ※  StackOverFlowError も同じ仲間 35
  36. 36. メモリリーク? あんますぐメモリリークとか言わない 36
  37. 37. OutOfMemory の起きる2つの原因 1. 同時に使うメモリが多すぎる サイジングのミス 過負荷 アプリケーションが大量のメモリを使う処理をしている 2. 使ったメモリ(の一部)を回収できず、実質的に使えるメモリ の量自体が減っている いわゆるメモリリーク 回収できないオブジェクトへの参照をヒープダンプで確 認し、コードを修正する 37
  38. 38. 2つの原因の区別 使用量をグラフにするとわかりやすい 長期的な傾向を見る 過負荷の場合 短い時間で急激に上昇する 負荷の少ない時間帯はメモリの空き領域が多い メモリリークの場合 長期間で徐々に上昇する 負荷の少ない時間帯の空き容量がだんだん回復しなくな る 38
  39. 39. メモリリークの調べ方の例 1. 定期的に(毎日決まった時間に1度、など)  GC.class_histogram を実行する 2. 1で取得したデータを比較して、継続的に増加しているオブジ ェクト(のクラス)を確認する 3.  GC.heap_dump を取得して2で確認したオブジェクトの参照状 況を確認する 4. コードを修正して、参照が残らないようにする。 ※ コマンドの実行時間は負荷の低い時間帯がおすすめです ノイズが少ないので調べやすい コマンドの処理コストがタダではない 39
  40. 40.  OutOfMemoryError に関する補足 今日は代表的なJavaヒープのOutOfMemoryErrorについて話しまし たが、Javaヒープ以外のメモリ領域が枯渇しても OutOfMemoryErrorが発生します。 ネイティブメモリ(JVM自身やネイティブライブラリで使われ る) Metaspace(JDK7以前ならPermanent領域) ログに OutOfMemoryError: <メッセージ> とメッセージが出るの で、あんまり見たことのないメッセージが出たらググったり本で 調べたりしましょう。 枯渇している領域が違えば当然調べ方も対策も変わってきます。 40
  41. 41.  OutOfMemoryError に関する補足その2  OutOfMemoryError がスローされたときにログに出るコールス タックは信用できる? 1つの処理が急激にメモリを使うようなケースでは、コー ルスタックがその処理であることが多い リークの場合はそうでもないことも多い 41
  42. 42. クラッシュの起きる(だいたい)3つの原因 1. JDK(JVM)にバグがある 2. リソースの枯渇(OutOfMemory, StackOverFlow) 3. アプリが呼び出したサードパーティー製ライブラリの問題 → 1はしんどいので、2と3を確認する 42
  43. 43.  3. アプリが呼び出したサードパーティー製ライブラリの問 題 の簡単なチェック  hs_err_pid<プロセスID>.log の最初の方を見る # # A fatal error has been detected by the Java Runtime Environment: # #  SIGSEGV (0xb) at pc=0x000000010d38011f, pid=27873, tid=0x000000000 # # JRE version: Java(TM) SE Runtime Environment (8.0_112‐b16) (build 1 # Java VM: Java HotSpot(TM) 64‐Bit Server VM (25.112‐b16 mixed mode b # Problematic frame: # V  [libjvm.dylib+0x58011f]  Unsafe_GetNativeByte+0x47 //★ ★のところにJVM(またはOS)以外のライブラリが表示され ていないかをチェックする コールスタックも見るとなお良い 43
  44. 44.  1. JDK(JVM)にバグがある  → 自分でまともに調べるのはかなり大変 JDK Bug System で調べるくらい → そもそもバグに当たらないことが最大の対策 ちゃんとアップデートする 三ヶ月に一回新しいのが出ます(1,4,7,10月) 44
  45. 45. その他解析ツール 障害解析を便利に行えたり、通常のコマンドではとりづらいデー タを取得できたりするツールもあるので、ケースによっては利用 を検討してみるのも良いかもしれません  Java Flight Recorder 、  HeapStats など… 45
  46. 46. HotSpot 以外のJVM ここまで話したのはHotSpot の話 HotSpot はJVM の代表的な実装(Oracle JDK, openjdk) それ以外のものもある 用途(強み)がはっきりしたものが多い傾向 同じ機能でも用語が違うことがある 一般にJVMに関する情報はHotSpotより少ない 最近では J9 や Zing の注目度が高い(気がする) 46
  47. 47. もうちょっと頑張りたい人に チューニング Javaパフォーマンス(オライリー) トラブルシュート Java Platform, Standard Editionトラブルシューティング・ガ イド 読み物 Java Magazine IBM developerworks オプションやコマンドを試してみたいとき easybuggy 47
  48. 48. 48

    Be the first to comment

    Login to see the comments

  • yoskhdia

    Mar. 21, 2017
  • k5jp1015

    Mar. 21, 2017
  • kmelancholiy

    Mar. 21, 2017
  • akiumihasegawa

    Mar. 21, 2017
  • 786201616

    Mar. 22, 2017
  • scova0731

    Mar. 23, 2017
  • shibataayumu

    Mar. 23, 2017
  • tanacasino

    Mar. 24, 2017
  • TsuyoshiCHO1

    Mar. 25, 2017
  • TasukuKakimoto

    Apr. 1, 2017
  • HirotoSakai

    Apr. 19, 2017
  • syobochim

    Apr. 26, 2017
  • KoheiTamura

    Jun. 12, 2017
  • HideyukiYabe

    Nov. 20, 2017
  • akyamano

    May. 15, 2019
  • youyamagata

    Jan. 30, 2020

あまり頑張りたくない人のためのJDK入門

Views

Total views

3,849

On Slideshare

0

From embeds

0

Number of embeds

488

Actions

Downloads

22

Shares

0

Comments

0

Likes

16

×