【Java】 Java のメモリ構造

Javaのメモリを理解するためのポイント

 * ガベージ・コレクション(GC)は、時間が掛かる
  => 時間が掛かるので、効率よくやるようにメモリ構造を工夫してある

ガベージ・コレクション(GC)

 * 以下の関連記事を参照のこと。
https://blogs.yahoo.co.jp/dk521123/37328410.html

Javaのメモリ構造(Java VM固有領域)

[1] Javaヒープ領域
 [1-a] New領域 (Young領域)
  1-a-1) Eden領域 ... 生成されたての比較的時間がたっていないインスタンスを保持
  1-a-2) Survivor 0 領域(S0。From)
  1-a-3) Survivor 1 領域(S1。To)
 [1-b] Old領域 (Tenured領域) ... インスタンス生成されてからある程度期間の経ったインスタンスを保持

[2] Nativeメモリ
 [2-a] Metaspace領域
 [2-b] Cヒープ領域          ... JavaVM自身のリソースを管理する領域。
 [2-c] スレッドスタック領域 ... スレッド毎に保持するスタック領域

補足:メモリ領域(静的領域 / スタック領域 / ヒープ領域) について

 * 以下の関連記事を参照のこと
https://blogs.yahoo.co.jp/dk521123/34569082.html

[1] Javaヒープ領域

 * JVM(Java Virtual MachineJava VM)により管理される

+---------+---------+
| New領域 | Old領域 |
+---------+---------+

 * 使用時間が長いオブジェクトは、Old領域に移る

 => 「長時間使っているインスタンス」=「今後も破棄される確率が少ないインスタンス」とし
    Old領域に置いとく。
    で、短時間で不要なインスタンスを頻繁に行い、ガベージ・コレクションを効率よく行う。

[1-a] New領域 (Young領域)

説明
 * オブジェクトが新たに作成されると、そのオブジェクトは、まず最初にEden(E)領域に配置される
 * Eden領域が新しいオブジェクトで一杯になると...
  => Scavenge GC(スカベンジGC、New領域のみのガベージ・コレクション。YoungGC (YGC)とも呼ばれる)
       が実行され、使用されていないオブジェクトは、破棄される
  => 現在も使用されていると判断されたオブジェクトは、SO(From)領域またはS1(To)領域へ移動し、
    メモリー上に残されるオブジェクトの候補となる
New領域が不足すると...
 => ScanvengeGC(YGC)が実行され、Eden領域をクリアし、再び新しいオブジェクトを受け入れるようになる
 => YGCを一定回数(MaxTenuringThresholdの値でデフォルトは32)繰り返した後で、
    JavaVMによって使用頻度が高いと判断されたオブジェクトは、破棄されずにOld領域へ移動する
補足
 * ScanvengeGCは、頻ぱんに起こるのが普通だが、少なからずパフォーマンスに影響するので、
  あまりにも多く発生する場合は、New領域を増やすことも検討する必要がある

[1-b] Old領域 (Tenured領域)

 * Tenured(テニュアド) = 寿命が長い
説明
 * New領域を対象としたYGC後に生き残ったオブジェクトが配置される
 * 配置されたオブジェクトは、ランタイム中に何度も利用される寿命の長いオブジェクトとして判断されたもの
Old領域が不足すると...
 => FullGC(フルGC、完全ガベージ・コレクション)が行う
 => FullGCが実行されると、ランタイムがいったん停止
 => Old領域に退避されていた不要なオブジェクトの破棄を最優先する
 => FullGCが頻発すると、パフォーマンスが悪くなる

[2] Nativeメモリ

 * OSが管理する領域

[2-a] Metaspace領域

注意
 * メモリの許す限り消費してしまう

補足:パーマネント領域 (非ヒープ領域)について

 * Java8からは外された
  => 確かに「java -XX:PermSize=128m -XX:MaxPermSize=128m」ってコマンドを実行しようとすると
     「support was removed in Java8.0」って言われる...
パーマネント領域(非ヒープ領域)
 * 以下のケースで、 Permanentサイズを大きく設定する必要がある
 1) ライブラリやフレームワークを利用する場合
 2) JSPJava Server Pages)を大量に使用する場合
 など
Permanent領域が不足すると...
 => FullGCが行われ、必要に応じてクラスの読み直しが発生
 => メモリが枯渇するとOutOfMemoryが発生

補足

 * 可能な限りFullGCが発生しないよう、Javaランタイムのヒープ・サイズを調整



関連記事

Javaガベージコレクション ( Barbage Collection; GC )

https://blogs.yahoo.co.jp/dk521123/37328410.html

JavaJVMのメモリ情報を出力させる

https://blogs.yahoo.co.jp/dk521123/33278121.html

Javaにおけるオブジェクトの使用メモリサイズの測る

http://blogs.yahoo.co.jp/dk521123/32941391.html

【フリーツール】【Java】メモリ監視ツール ~Eclipse Memory Analyzer~

https://blogs.yahoo.co.jp/dk521123/33092315.html

Instruction の getObjectSize で、オブジェクトの使用メモリサイズを測る

http://blogs.yahoo.co.jp/dk521123/32945695.html