2013/09/03

jvm memory system jconsole

★jvm memory model
・eden領域 (ヒープ)-> エデンの園 人類の始祖 Adam と Eveのが住んでいる楽園、ほとんどのオブジェクトにメモリーが最初に割り当てられるプール

・Survivor領域 (ヒープ)->生き残った人。Eden 領域のガベージコレクションで残ったオブジェクトを含むプール。

・Tenured世代 (ヒープ)->終身在職権のある(いわゆる正社員)。Survivor 領域である程度の期間存続したオブジェクトを含むプール

Permanent 世代 (非ヒープ)->永久的な。クラスやメソッドオブジェクトなど、仮想マシン自体を反映したデータをすべて保持するプール。Java VM でクラスデータ共有を使用する場合、この世代は読み取り専用領域と読み取り/書き込み領域に分割される

コードキャッシュ (非ヒープ):HotSpot Java VM には、ネイティブコードのコンパイルと保存に使用するメモリーを含むコードキャッシュも含まれる



★ヒープおよび非ヒープのメモリー
Java VM が管理するメモリーには、ヒープメモリーと非ヒープメモリーの 2 種類があり、いずれも VM の起動時に作成される
ヒープメモリーは実行データ領域で、Java VM はそこからすべてのクラスのインスタンスと配列にメモリーを割り当てる。ヒープのサイズは可変の場合と固定の場合がある。ガベージコレクタは、ヒープメモリーをオブジェクトに再利用する自動メモリー管理システムである
非ヒープメモリーには、Java VM の内部処理や最適化に必要なメモリーと、すべてのスレッドで共有されるメソッド領域が含まれる。非ヒープメモリーには、実行定数プール、フィールドおよびメソッドデータ、メソッドおよびコンストラクタのコードなど、クラス単位の構造体が格納される。メソッド領域は論理的にはヒープの一部が、実装方法によっては、Java VM がこの領域のガベージコレクトや圧縮を行わない場合もある。ヒープと同様に、メソッド領域のサイズは固定の場合と可変の場合がある。メソッド領域のメモリーは連続している必要はない。
=>動的物をビーフに、静的な物を非ビーフに。。。



★メモリープール メモリーマネージャー
メモリープールとは、Java VM が管理するメモリー領域である。Java VM には少なくとも 1 つのメモリープールがあり、実行中にメモリープールを作成または削除できる。メモリープールは、ヒープメモリーと非ヒープメモリーのどちらかに属する。

・メモリーマネージャーは、1つまたは複数のメモリープールを管理する。ガベージコレクタは、メモリーマネージャーの一種で、アクセスできなくなったオブジェクトが使用していたメモリーの再利用を管理する。Java VM が装備するメモリーマネージャーは 1 つの場合も複数の場合もある。実行中にメモリーマネージャーを追加または削除できる。メモリープールは、複数のメモリーマネージャーによって管理できる。
=>ガベージコレクタは、メモリーマネージャーの一種



★ガベージコレクション
ガベージコレクション (GC) は、参照されていないオブジェクトが使用していたメモリーを解放する。アクティブな参照をもつオブジェクトを「生きている」と考え、参照されていない (アクセスできない) オブジェクトを「死んでいる」と考えるのが一般的である。GC によって使用されるアルゴリズムとパラメータがパフォーマンスに劇的な効果をもたらす可能性がある

Java HotSpot VM ガベージコレクタは、世代別 GC を使用する。世代別 GC は、ほとんどのプログラムには次のような傾向があるという所見に基づいている
    !!!生成する多くのオブジェクトは短命である (反復子やローカルの変数など)。
    !!!生成する一部のオブジェクトは非常に長い寿命をもつ (高度な持続性オブジェクトなど)。
そのため、世代別の GC は、メモリーをいくつかの世代に分け、それぞれにメモリープールを割り当てる。ある世代が割り当てられたメモリーを使用すると、VM はメモリープール上で部分的な GC (マイナーコレクションともいう) を実行し、死んだオブジェクトによって使用されたメモリーを再利用する。この部分的な GC は、通常、フル GC よりもはるかに高速である
=====>あ、ああ。。。JVMも格差社会だ。。。

Java HotSpot VM は、若い世代 (「nursery」ともいう) と古い世代という 2 つの世代を定義している。若い世代は、1 つの「Eden 領域」と 2 つの「Survivor 領域」で構成される。VM は最初にすべてのオブジェクトを Eden 領域に割り当て、ほとんどのオブジェクトはそこで死にする。マイナー GC を実行するとき、VM は残りのオブジェクトを Eden 領域から Survivor 領域の 1 つに移す。VM は、Survivor 領域で十分に長く生きるオブジェクトを古い世代の「Tenured」領域に移す。Tenured 世代がいっぱいになると、フル GC が実行される。これは生きているオブジェクトをすべて含むため、通常は マイナー GC よりも時間がかかる。Permanent 世代は、クラスやメソッドオブジェクトなどの仮想マシン自体を反映したデータをすべて保持する
====>要は、非正規雇用の若い世代(楽園と生存者)のリストラはやりやすく、正社員(Tenured)は時間かかるね。。。

-Xms初期ヒープサイズ(全体)
-Xmx最大ヒープサイズ(全体)
-Xmn (-XX:NewSize)young generation領域サイズ
-XX:NewRatioyoung generation領域とtenured generation 領域の比率
-XX:SurvivorRatioeden領域とsurvivor領域の比率
-XX:TargetSurvivorRatioyoung generation が full になるまでに survivor space で利用可能なスペースの比率
-XX:MinHeapFreeRatioGC 後に拡張されるまでに消費されるヒープの比率
-XX:MaxHeapFreeRatioGC 後にシュリンクされるまでに消費されるヒープの比率


★jconsole memory display
・USED「使用済み」: 現在使用中のメモリー容量。
・COMMITTED「確保済み」:Java VM で利用できることが保証されたメモリー容量、確定メモリーの容量は必ず使用中のメモリー容量以上である
・MAX「最大」:メモリー管理に使用できる最大メモリー容量。ava VM で使用メモリー容量を確定メモリー容量より大きくしようとすると、使用量が最大メモリ容量以下の場合 (たとえば、システムの仮想メモリーが少ない場合)でも、メモリー割り当てに失敗することがある==>いわゆる、保証がない。。
・GC time「GC 時間」: ガベージコレクションに要した累積時間とその呼び出しの総数。複数行に及ぶ場合もあります。各行は Java VM で使用するガベージコレクタの 1 つのアルゴリズムを示す
==>VM で使用するガベージコレクタのアルゴリズム


★そもそも、GC プロセスは、メモリ(セントラル・ストレージ)上の物理アドレスに依存する処理を実行するスレッドで、実行時には
アプリケーションの処理を停止させるものです
=>incremental、すこしずつの意味

★ヒープサイズが大きいと、GC の起動回数は減りますが、一回の GC に必要な時間が長くなり、その過程の、アプリケーション停止時間 (stop-the-world) も長くなって、レスポンスタイムに問題が発生する可能性があります。