「オブジェクト指向でなぜ作るのか(第二版)」の第五章を読んだメモ。
Javaの場合について説明する。
TODO: 本の図をを貼るなり自分で書くなりする。
静的領域
- グローバル変数(クラス情報)とコード情報が確保される。
- プログラムの開始時に保持され、終了まで配置は固定される。
以下Javaの場合、
- クラスは必要になった際に逐次ロードすることから、クラス情報が乗る場所は実行時に決まるので静的領域ではなく、メソッドエリアと呼ばれるヒープ領域の一部に載せる。このメソッドエリアはGCの対象にならない。
- メソッドの一覧を「メソッドテーブル」として持っており、メソッドを呼び出した際には、これを経由して、同じく静的領域内にロードされた目的のメソッドのデータを呼び出している。
-
ChildClass
がParentClass
を継承している場合、overrideされていないメソッドに関しては、ChildClassのメソッドテーブルはParentClassとして保持されているメソッドの実体を参照している。
ヒープ領域
- プログラムの実行時に動的に確保される(ここを使いすぎると、メモリリークが生じる)
以下Javaの場合、
-
インスタンスの実体はこの領域にロードされている。
- インスタンスを指定してメソッドを呼び出す仕組みを実現するため、メソッドエリア内のクラス情報への対応づけもされている。
-
ChildClass
がParentClass
を継承している場合、ChildClass
のインスタンス変数は親のものをコピーし、独自の物として保持している。(メソッドのように、親クラスのものを参照しているわけではない)
スタック領域
- 一つのスレッドに一つのスタック領域が確保される。
- LIFOで、(実行中のサブルーチンに与えられた引数、ローカル変数、戻り先)を突っ込んでいく。
以下Javaの場合、
- ローカル変数が保持されている。
- ローカル変数としてオブジェクトを宣言・代入した場合、実際のところ、その変数に入っているのは「ヒープ内のどこにインスタンスのデータがロードされているのかを表すポインタ」。
ガーベッジコレクションの仕組み
以下、(少なくとも)Javaの場合、
- ヒープ内のもう使われていないオブジェクトのデータを消して回る
- もう使われていない = ヒープからもスタックからも直接あるいは間接的に参照されていない
- ガーベッジコレクション専用のスレッドが立っていてこの中で行われる。
メモ
確保していく<---- ヒープ | スタック --->確保していく
OSによって、メモリのバッファの最大値は決まっている倍もあるしやりくりできる場合もある。
(再帰の深さによる制限もある)