主要討論默認的Serial/Serial Old內存分配:
一、幾種分配方案
1. 對象優先在Eden分配;
一般情況下,對象會在新生代的Eden區分配,Eden區沒有足夠空間時,虛擬機會 發起一次MinorGC;當MinorGC時,若無法放入survivor空間,就會再通過分配擔保機制轉移到老年代中;
2. 大對象直接進入老年代;
通過 -XX:PretenureSizeThreshold參數設置;
3. 長期存活的對象進入老年代:
通過 -XX:MaxTenuringThreshold參數設置;每MinorGC一次還存活在Survivor中,則年齡加1;
4. 組團進入 老年代:
在survivor中年齡相同的所有對象大小總和大於 PretenureSizeThreshold 參數的一半,年齡大於或等於該年齡的對象進入老年代。
5. 空間擔保進入 老年代:
每次MinorGC之前,會檢查老年代最大連續可用空間是否大於 新生代所有對象的總空間,大於則表示安全可進行MinorGC;
如果小於:(JDK 6U24不再檢查HandlePromotionFailure,一定會冒險)
a. 檢查HandlePromotionFailure 為 true ,表示允許冒險,則與歷次晉升到老年代的對象平均大小比較,若大於則進行MinorGC,若小於則進行FullGC;
b. HandlePromotionFailure 為 false,進行FullGC;
二、MinorGC 與FullGC/Major
MinorGC:指發生在新生代的GC,因大多數新生對象生命周期很短,所以MinorGC通常很頻繁,回收速度也較快;
MajorGC/FullGC:指老年代GC,速度一般較慢,一般是MinorGC的10倍;通常MajorGC會伴隨一次MinorGC;(書原話,有歧義)
參考知乎R大答案:Major GC和Full GC的區別是什么?觸發條件呢?
觸發條件:
MinorGC:Eden區滿時觸發;FullGC也會伴隨有MinorGC;通常會使得Old gen變大;
FullGC:a. MinorGC觸發前,檢查歷次進入老年代的平均大小,若小於則FullGC;
b. 如果有永久代(perm gen),在不足哆分配時,觸發FullGC;
c. 調用System.gc(),提醒JVM FullGC,但不可控;
三、HotSpot幾個區域
新生代分為:Eden Space、Survivor Space
老年代:Tenured Gen
永久代:Perm Gen(方法區相關數據);
在 JDK 1.8 中, HotSpot 已經沒有 “PermGen space”這個區間了,取而代之是一個叫做 Metaspace(元空間) 的東西。
擴展:Java8內存模型—永久代(PermGen)和元空間(Metaspace)