JVMのメモリとGCを復習する
JavaVMのメモリとGCを復習する。
メモリ構造と設定オプション
ヒープ Javaヒープ: 最大:-Xmx, 初期:-Xms New: サイズ:-Xmn, NewとOldの割合:-XX:NewRatio Eden Survivor: SurvivorとEdenの割合:-XX:SurvivorRatio Old Permヒープ: 最大:-XX:MaxPermSize, 初期:-XX:PermSize Cヒープ スレッドスタック: 1スタックの最大:-Xss
※全て非標準オプションおよびHotSpot VM Specific Options
※Javaヒープ:newで確保される領域
※Permヒープ:クラス等のメタデータが格納される領域
※Cヒープ:JavaVM自身のリソースが格納される領域。スレッドのスタックなど
GC
JavaVMによる、使用済みメモリ領域(主にJavaヒープ)の回収・空き領域の確保。
大まかな流れ:Eden=CopyGC⇒Survivor=…⇒Old
(Edenが一杯になるとCopy GCによりSurvivorへ。この際、Eden内・Survivor内の参照なしオブジェクトは廃棄される。これを繰り返して、Survivorにずっと残り続けたオブジェクトはOldへ。Oldが一杯になったらFull GC)
OutOfMemoryError
主に、Javaヒープが不足している場合に投げられる。
Javaヒープ不足である場合は、スタックトレースに「java.lang.OutOfMemoryError: Java heap space」と出力され、JavaVMの実行は継続する。
Cヒープ不足の場合は、スタックトレースの先頭が Native Method である。
なお、OutOfMEmoryErrorが表示されてJavaVMが強制終了された場合は、Cヒープ不足である。
実験
テストコード
public class Test { public static void main(String[] args) { int roopCount = 1000000; int toOldTiming = 10; // 何ループ毎にOld領域まで生かすオブジェクトとするか String[] old = new String[roopCount/toOldTiming]; for(int i = 0; i < 1000000; i++){ String test = "test"+i; if(i % toOldTiming == 0) { old[i/toOldTiming] = test; } } } }
テストコマンド
javac Test.java java -Xmx2m -Xloggc:gc.log -XX:-PrintGCDetails Test