JVMのメモリモデル

勉強したことをメモ。

参考文献

以下記事が大変参考になった。

Javaパフォーマンスチューニング(3):Javaのヒープ・メモリ管理の仕組み (1/2) - @IT

第5回 チューニングのために理解しておきたいGCの4つのアルゴリズム:Javaはどのように動くのか~図解でわかるJVMの仕組み|gihyo.jp … 技術評論社

Java8のHotSpotVMからPermanent領域が消えた理由とその影響 | ギークを目指して

JVMのメモリ領域

大きく分けて「newしたオブジェクトを配置するヒープ領域(New領域+Old領域)」「その他、JVMの管理用変数を保持する領域(Permanent領域 or Metaspace領域+C Heap領域+ThreadStack領域)」からなる。

ヒープ領域

Javaでnewしたオブジェクトは、この領域にメモリ確保される。GCの処理の関係で、3つのセグメントを転々とする。

Eden領域

New領域と言われるものの1つ。
Javaでnewしたオブジェクトがまず最初に格納される。Scavenge GC という頻繁に行われるGCの対象領域。

Scavenge領域

New領域と言われるものの1つ。
「From領域+To領域」ともいわれる。
Eden領域にいながら1回のGCで破棄されなかったオブジェクトがコピーされてくる。真っ二つに分割されており、1回のGCコピーでは「Eden領域+片方の領域に残ってたもの」を「もう片方の領域に詰めながらコピー」。その次のコピーは反対に使う。その次はまた戻って・・・と「From」「To」の役割をフリップさせながらGCしながらコピーする。
この領域も、Scavenge GC という頻繁に行われるGCの対象となる。
JVMオプションで設定された回数だけ、オブジェクトはここに残る。

Old領域

Scavenge領域で、JVMオプションで設定された回数GCをしてもまだ残っているオブジェクトが移動される。
こちらは、Scavenge GC という頻繁に行われるGCの対象とならず、Full GCという大掃除の際にしかGCされない。

その他領域

超ざっくりした分類だが、これ以降はJVMの実装に深くかかわる。

Permanent領域 or Metaspace領域

クラスやメソッドのメタ情報を保持する領域。
ClassLoaderはclass fileを読み込んでここに書き込む。
Java 8 でPermanent領域は廃止され、Metaspace領域になった。
ちなみに、OutOfMemory対策に指定するオプション-XX:PermSizeは、Permanent領域のサイズ指定オプション。
(よくもまあ、知らずに使っていたものだ・・・)
ちなみに、Permanentは、正確にはヒープ領域に属するようだ。

C Heap領域

JavaVMの実装が使う、専用の領域。
OutOfMemoryが出ないクラッシュは、たいていここのOverrunだそうだ。(スレッドいっぱい作った時とか)

Thread Stack領域

いわゆるスタック領域。Javaのローカル変数などが書き込まれる。
少し驚いたのだが、Javaのスタックは、ブロック単位で積まれる。
つまり、forやifでブロックを組むことは、関数呼び出しに相当するとまではいかないが、それなりにコストを払った処理になる。