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.

2012年javaメモリリーク

Java読書会BOF 2012合宿で発表した、Javaアプリケーションのメモリリークの調査方法についてのスライド。
主にOracle JDK標準ツールでGCの動作を見る方法について紹介している。また、finalizeメソッド実装クラスがGCに与える影響についても述べている。

  • Be the first to comment

2012年javaメモリリーク

  1. 1. Java メモリリーク? 2012/02/11 Java読書会BOF 高橋 徹
  2. 2. アジェンダ <ul><li>Java メモリ管理 </li></ul><ul><ul><li>ガベージコレクションの前提 </li></ul></ul><ul><li>サンプルアプリケーション </li></ul><ul><ul><li>気象センサーアプリケーション </li></ul></ul><ul><li>Java ヒープの推移をみる </li></ul><ul><ul><li>JDK 標準ツール </li></ul></ul><ul><li>Finalize の脅威 </li></ul><ul><li>最後に </li></ul>
  3. 3. Java メモリ管理 – 自動だよね? <ul><li>Java は Garbage Collection を搭載 </li></ul><ul><ul><li>メモリの解放からプログラマは解放された‥はず </li></ul></ul><ul><li>メモリの管理を気にしなくていいから、何の GC がどう動いているか、気にしない </li></ul><ul><li>問題が起きてから、初めて気にすることに </li></ul><ul><ul><ul><li>OutOfMemoryError, 応答性/スループット劣化 , ・・・ </li></ul></ul></ul>
  4. 4. Java メモリ管理 – GC の種類 <ul><li>Java SE 7 Runtime で用意される GC の種類 </li></ul>GC 種類 新世代 旧世代 課題 シリアル コピー/逐次 全てを止める マーク・スイープ・コンパクト 逐次/全てを止める 旧世代 GC の停止時間が増大 パラレル コピー/並列 全てを止める マーク・コンパクト/並列 全てを止める 複数 CPU 必要(≧ 4 ) コンカレント マーク・スイープ/並行 旧世代 GC が常時動作するのでスループット低下 G1 マーク・スイープ + コンパクト 並列/全てを止める 新顔につき課題はこれから明らかに?
  5. 5. Java メモリ管理 – GC の種類 <ul><li>GC の方式について解説している書籍 </li></ul>著者:中村成洋、相川光、竹内郁雄(監) 出版:秀和システム、 2010 年
  6. 6. Java メモリ管理 – GC 情報源 <ul><li>GC ほか JavaVM の詳細情報 </li></ul><ul><li>“ Troubleshooting Guide for Java SE 6 with HotSpot VM”, 2008.11 </li></ul><ul><li>Oracle のサイトで HTML / PDF 公開 </li></ul><ul><li>http://www.oracle.com/technetwork/java/javase/tsg-vm-149989.pdf </li></ul>
  7. 7. Java メモリ管理 – GC の種類 <ul><li>GC の速さ </li></ul>超高速 高速 超低速 低速 GC 種類 新世代 旧世代 課題 シリアル コピー/逐次 全てを止める マーク・スイープ・コンパクト 逐次/全てを止める 旧世代 GC の停止時間が増大 パラレル コピー/並列 全てを止める マーク・コンパクト/並列 全てを止める 複数 CPU 必要(≧ 4 ) コンカレント マーク・スイープ/並行 旧世代 GC が常時動作するのでスループット低下 G1 マーク・スイープ + コンパクト 並列/全てを止める 新顔につき課題はこれから明らかに?
  8. 8. Java メモリ管理 – デフォルト GC <ul><li>java –jar myapp.jar を実行すると? </li></ul><ul><ul><li>Java SE は実行時に環境に応じて GC を選択する </li></ul></ul><ul><ul><li>Windows OS では </li></ul></ul><ul><ul><ul><li>2 CPU 以上かつ 2GB RAM 以上の PC で </li></ul></ul></ul><ul><ul><ul><li>  Window OS 上で 64bit 版 Java </li></ul></ul></ul><ul><ul><ul><ul><li>->  パラレルコレクタ </li></ul></ul></ul></ul><ul><ul><ul><li>それ以外 シリアルコレクタ </li></ul></ul></ul><ul><li>なお、 JavaVM オプションで随意に GC 選択可 </li></ul><ul><ul><ul><li>但し、激しく面倒くさい </li></ul></ul></ul>
  9. 9. Java メモリ管理 – 前提 <ul><li>Java 2( HotSpot VM )は、世代別 GC </li></ul><ul><ul><li>「多くのオブジェクトは若くして死ぬ」という経験則に最適化した GC </li></ul></ul><ul><li>極力 Full GC (旧世代領域の GC )を避ける </li></ul><ul><ul><li>旧世代 GC は遅い </li></ul></ul>
  10. 10. サンプルアプリケーション <ul><li>気象センサー収集アプリケーション </li></ul><ul><ul><li>多数の気象センサー(百葉箱)から気象情報を集める </li></ul></ul><ul><ul><li>気象センサーの計測間隔はまちまち </li></ul></ul><ul><ul><ul><li>サンプルでは、2秒、 30 秒、3分 の 3 種類の異なる寿命のデータを発生 </li></ul></ul></ul><ul><ul><li>新世代で GC されず旧世代に移るインスタンスが定常的に発生する </li></ul></ul>
  11. 11. サンプルアプリケーション <ul><li>デモ </li></ul>
  12. 12. JDK – JVisualVM <ul><li>JDK 標準ツール </li></ul><ul><li>取り扱い説明は、 Java SE 6/7 Documentation に含まれている。 </li></ul><ul><li>-> docstechnotesguidesvisualvm フォルダ </li></ul>
  13. 13. 脱線  JDK – Document <ul><li>Java SE ドキュメントのトップページは </li></ul>
  14. 14. 脱線  JDK – Document <ul><li>Java SE ドキュメントのトップページは </li></ul>
  15. 15. 脱線  JDK – Document <ul><li>Java SE ドキュメントのトップページは </li></ul>おなじみの Javadoc API ページはここから JVisualVM の説明ページはここから
  16. 16. JDK – JVisualVM 標準では GC に関する計測項目は、 JConsole に劣るが・・・
  17. 17. JDK – JVisualVM [ ツール ] メニュー-> [ プラグイン ] から Visual GC プラグインを追加すると・・・
  18. 18. JDK – JVisualVM リアルタイムに GC の動きが 把握できます
  19. 19. JDK – JConsole <ul><li>JDK 標準ツール </li></ul>
  20. 20. JDK – JConsole Eden, Survivor, Tenured などの各ヒープ個別のメモリ使用推移を調査できます。
  21. 21. OS ツール <ul><li>Windows OS ではパフォーマンスモニタ </li></ul><ul><ul><li>Java プロセス自体のメモリ使用量を計測 </li></ul></ul><ul><li>Unix 系 </li></ul><ul><ul><li>vmstat あたり? </li></ul></ul>
  22. 22. JDK – コマンドライン派 <ul><li>JDK 標準ツール </li></ul><ul><ul><li>jmap </li></ul></ul><ul><ul><li>jstat </li></ul></ul><ul><li>JavaVM オプション </li></ul><ul><ul><li>-Xloggc:path/to/gc.log など </li></ul></ul>
  23. 24. メモリ使用調査 <ul><li>JVisualVM の Visual GC </li></ul>Eden が一杯になりマイナー GC が周期的に実施 Survivor を生き残るインスタンスが多数いる じわじわと旧世代領域が消費され、フル GC が頻発するように
  24. 25. メモリ使用調査 <ul><li>JVisualVM のサンプラ – メモリー </li></ul>ヒープに占めるインスタンスをクラスごとに集計し多い順に表示(ヒストグラム)
  25. 26. メモリ使用調査 <ul><li>Jconsole – メモリー </li></ul>survivor が常にさちっていて、 どんどん旧世代の使用が増え、 フル GC が頻発している様子が見える
  26. 27. GC の調整(1) <ul><li>シリアルコレクタで新世代を大きくしてみる </li></ul>新世代/旧世代のヒープサイズを等しくしてみた。   JVM オプション   &quot;-XX:NewRatio=1“ 【結果】 新領域があふれる頻度がやや減ったがフル GC 発生頻度が増えた。 GC 効率は劣化したといえる。
  27. 28. GC の調整(1) <ul><li>シリアルコレクタで新世代を大きくしてみる </li></ul>
  28. 29. GC の調整(2) <ul><li>コンカレントコレクタを使ってみる </li></ul>あまり景色が変わっていない マイナー GC 、フル GC を繰り返しながら増加傾向にある JVM オプション -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalMode ※ CPU が 1 個なので、 UseParNewGC は指定せず、 IncrementalMode を指定
  29. 30. GC の調整(2) <ul><li>コンカレントコレクタを使ってみる </li></ul>使ってみたが、微妙な感じ
  30. 31. Finalize の脅威 <ul><li>気象データの一部を、 finalize メソッドを実装したクラスに置き換えてみると </li></ul>前回見られなかったヒープ使用量増大傾向が確認できる 旧世代ヒープが増加傾向 survivor も時間とともにあふれが見られる
  31. 32. Finalize の脅威 <ul><li>Finalizer インスタンスの数に着目 </li></ul>1 万超の Finalizer インスタンスがある finalize 実装メソッド。 1 万超のインスタンスがある
  32. 33. Finalize の脅威 <ul><li>JConsole のファイナライズ関連計測値 </li></ul>GC のファイナライズ処理待ちインスタンスが 1 万超
  33. 34. Finalize の脅威 <ul><li>finalize を実装したクラスは、 GC に 2 段階必要とするため、大量に生成し不要になっても、メモリが実際に解放されるまでには時間がかかる。 </li></ul><ul><li>finalize は使用しない( Effective Java 第 2 版にもある) </li></ul><ul><li>どうしても避けられないときは、明示的に </li></ul><ul><ul><li>System.gc(); </li></ul></ul><ul><ul><li>System.runFinalization(); </li></ul></ul><ul><ul><li>を呼ぶことも考慮する </li></ul></ul>
  34. 35. 最後に <ul><li>Java では、プログラミング中はメモリリークを気にする必要はありません。 </li></ul><ul><li>アプリケーション稼働中は、大いに気にする必要があります。 </li></ul><ul><li>GC のチューニングは茨の道です。ひたすらデータを採取し変更結果を評価するのみ。 </li></ul>

×