こんにちは!ワーパパエトウです!
今回はJavaのインスタンスがJVMによってどのように配置され消滅していくのかについて、ガーベッジコレクション(以降、GC)の話も絡めつつ解説していきます。
メモリ領域の構成と用語解説
Java7までの構成

Java7までのメモリ空間は上図の通り、大きくヒープとスタックとCヒープに分かれていました。
さらにヒープはYoung領域とOld領域とPermanent領域に分かれ、Young領域はEden領域、From領域、To領域で構成されています。
そして、マイナーGCの対象はYoung領域で、フルGCの対象はヒープ全体でした。
※後述にて用語解説あり
Java8以降の構成

Java8以降のメモリ空間は上図の通り、Java7までと大きく変わった点として、Permanent領域が廃止されネイティブメモリにMetaSpaceが新設された点です。
いままでJVMが確保していたPermanent領域だったのに対して、MetaSpaceをネイティブメモリに作ったことで容量に上限が無くなったことになる。
これはメリットである反面デメリットでもある。つまり、メモリリークなどが発生していた場合、気付かぬ内にメモリを食い尽くしていたなんてことも起こり得るということです。
こちらについては上限値を設定することが出来るようなので忘れないようにしたいところです。
それから話を戻しますが、本構成のマイナーGCの対象はYoung領域で、フルGCの対象はヒープ全体+MetaSpaceです。
用語解説
# | 用語 | 説明 |
---|---|---|
1 | ヒープ | JVMが確保しているメモリ空間。生成されたインスタンスはこの領域に配置する。 |
2 | Permanent | 静的なものを配置しておく領域。ロードされたクラスやメソッド、Static変数などを配置する。 |
3 | MetaSpace | Java8以降、Permanent領域の代わりに登場した領域。JVM固有のメモリでなくネイティブメモリに存在するので容量は大幅に向上した。 格納情報としてロードされたクラスやメソッドはそのままだが、Staticな変数などはヒープ領域に置いてきている。 |
4 | スタック | プリミティブ型の変数、参照型の変数の配置先アドレス(番地)を配置する。 |
5 | Cヒープ | JVM自身が存在している領域。ネイティブライブラリを使用する場合もこの領域を使用する。 |
インスタンスの生成から消滅まで

下記の順番にオブジェクトを移動させます。
① インスタンスを生成したら、まず初めに配置するのがEden領域です。
② マイナーGCが走るとYoung領域の不要オブジェクトを削除します。必要なオブジェクトはそれぞれ下記の通り移動させます。
a.Eden領域→From空間
b.From空間→To空間
c.To空間→From空間
③ ②を繰り返して「From空間⇔To空間」の移動が規定の回数(デフォルトは7回)を超えた場合はそのオブジェクトをOld領域に移動させます。
④ ②および③を繰り返し、Old領域のオブジェクトが満杯になるとフルGCが発生します。マイナーGCと違い、フルGCはヒープ全体をGCするため時間が掛かります。そのため、可能な限りマイナーGCだけで済むようにプログラムを組みたいですね。
さいごにまとめ
今回はJVMが扱っているヒープ領域を中心に解説しました。また、スタック領域を中心に解説した記事も書いていますのでそちらも参考にしてください。

では今回はここまで!また次回お会いしましょう!
コメント