Javaヒープ

ヒープ

http://d.hatena.ne.jp/tanakakns/20120508/1336467306

^^^^^JavaヒープJavaVM上で起動するJavaプログラムのリソースを管理する領域。New領域とOld領域で構成される。
^^^New領域新規オブジェクトと閾値(-XX:MaxTenuringThreshold)未満のオブジェクトが配置される。(Young領域とも呼ばれる)
Eden領域新規のオブジェクトが配置される。
From領域CopyGC(ScavengeGC、マイナーGC)が実行された際に、使用中のオブジェクトはここへコピーされる。(S0やS1とも呼ばれる)
To領域CopyGC(ScavengeGC、マイナーGC)が実行された際に、使用中のオブジェクトはここへコピーされる。(S0やS1とも呼ばれる)
Old領域New領域で閾値(-XX:MaxTenuringThreshold)を超えたオブジェクトが配置される。(Tenured領域とも呼ばれる)
Permanent領域クラスやメソッドの情報が格納される領域であり、アプリケーション起動後はほとんど増減しない。
CヒープJavaVM自身のリソースを管理する領域。NativeMethod、Javaスレッド自身、(8k以上の)バッファ領域として利用される。
スレッドスタックスレッド毎に保持するスタックの領域。
※「New領域」=「Eden領域」+「From領域」+「To領域」
※From、To領域をあわせてSurvivor領域と呼ぶ。

ヒープの使用状況を確認する方法

http://d.hatena.ne.jp/tanakakns/20120508/1336467306

  • jstat
    • JDKにデフォルトで同梱されているコマンド。
    • -gcutilオプションで、From(S0)、To(S1)、Eden、Old、Permanent領域ごとの使用率やマイナーGC、Full GCの発生回数、GCの実行時間累計が確認可能。
    • すでに起動中のJavaプロセス(jpsコマンドで取得)のヒープの使用状況をリアルタイムに確認することができる。
    • (例)jstat -gcutil -h10 <pid> 5000
  • jconsole

ヒープダンプの統計情報を取得する方法

  • -XX:+HeapDumpOnCtrlBreakを設定しておき、kill -3 <pid>を実行 (Java 1.5の場合)
  • -verbose:gc(-Xloggc:<path_to_file>)、-XX:+PrintClassHistogramを設定しておき、kill -3 <pid>を実行
  • jmap -heap:format=b <pid>(Java 1.5の場合)
    • 「heap:format=b」はバイナリで出力するという意味
  • jmap -dump:format=b,file=filename <pid>(Java 1.6の場合)
    • 実行できなかった場合は「jmap -F -dump:format=b,file=filename <pid>」で実行してみる
  • -XX:+HeapDumpOnOutOfMemoryErrorを設定しておき、OutOfMemoryErrorが発生

※上記の方法で詳細なヒープ情報を取得可能であるが、出力には時間がかかり、また負荷も大きいので注意が必要。

ヒープダンプ解析ツール

  • VisualVM
    • JDKにデフォルトで付いているのでお手軽。「jvisualvm」と打ってみる。
    • アプリケーションのスナップショット(.apps,.)、スレッドダンプ(.tdump)、ヒープダンプ(.hprof,.)、プロファイルのスナップショット(.nps,*.npss)を読み込むことができる
  • Eclipse Memory Analyzer
    • 怪しい部分を指摘してくれるので便利。
  • HeapAnalyzer
  • HAT (Heap Analysis Tool)
    • JDKにデフォルトで付いている。「jhat」と打ってみる。

プロファイラ

オブジェクトの生成、GC等、JVMの挙動をトレースする。アプリケーションを動作させつつ、増加していくオブジェクトを探したり、スタックトレースを確認したり等の調査が 可能。

パフォーマンスが悪化するため、運用環境では通常使用できない。

メモリリークやメモリの大量消費の調査の場合、まず問題の再現方法を突き止めた上で、開発/検証環境でプロファイラを使用して、再現方法を実施して、増加したオブジェク トを解析する。

  • NetBeans Profiler

[[Java講座 [Javaのメモリ管理 - GC、ガベージコレクション、Heap ]|http://www.site-cooler.com/java/j2se/memory.htm]]

JavaHeap領域とは、PC上のメモリのような役割を持っており、

JVMの作業用領域として使用されます。JVM 毎に一つずつ割り当てられ、

JVM上で動作する全てのスレッドから共有されます。

JavaHeapにはクラスやインスタンス化されたオブジェクトが格納されます。

この領域はガベージコレクションの対象エリアであり、

この領域にオブジェクトを格納しようとして領域を確保できない場合

(verbose:gcの出力では Allocation Failure が出力されます)

ガベージコレクションが行われ、領域が整理してオブジェクトを格納できるようにします。

ガベージコレクションを行っても領域が確保できなかったり、

なんらかの理由で確保失敗した場合 stdout または stderr にjava.lang.OutOfMemoryError がスローされます。

このサイズを設定するには Javaのコマンドラインオプションで、

最大値「-Xmx」、最小値「-Xms」を設定します。

[ JavaHeapの最大を 512Mに設定]
java -Xms512m

@IT:Javaパフォーマンスチューニング 第3回

図1は、JVM におけるヒープ・メモリの構造を示したものです。

この図が示すように、ヒープ・メモリの中には新しいオブジェクトを格納する「NEW」領域と、

古いオブジェクトを格納する「OLD」領域が存在します。

生まれてすぐに不要となる短命なオブジェクトはNEW領域でその一生を過ごし、

長時間存在するオブジェクトはOLD領域に留まることになります。

また、図1には示されていませんが、ヒープ・メモリにはJVMにロードされたクラスの置き場所として利用される「Permanent」領域も存在します。