內存分配與回收策略
本次讀書筆記主要研究新生代Minor GC在幾種垃圾收集器中的運行。第一次看Java相關的書,第一次在網上寫讀書筆記,給自己記錄一下( ?? ω ?? )y。大部分都是書上的原話,總結加自己實現對比一下而已。
public class MinorGC {
private static final int _1MB = 1024*1024;
/**
* VM參數: -verbose:gc -Xms20M -Xmx20M -Xmn10M
* -XX:+PrintGCDetails -XX:SurvivorRatio=8
*/
public static void main(String[] args) {
byte[] allocation1, allocation2, allocation3, allocation4;
allocation1 = new byte[2 * _1MB];
allocation2 = new byte[2 * _1MB];
allocation3 = new byte[2 * _1MB];
allocation4 = new byte[4 * _1MB];
}
}
Serial收集器
該收集器是一個單線程收集器,垃圾收集時必須暫停其他所有工作線程——Stop The World。
優點:無線程交互開銷,簡單高效。
缺點:暫停響應。
書上運行上述代碼的結果是:
GC前,allocation1-3分配到新生代Eden區,占用6M,剩余的2MEden空間不夠分配allocation4,產生Minor GC。
GC時,3個2M的對象allocation1-3不能放入1M的Survivor空間,于是轉移到老年代。
GC后,allocation4順利分配到Eden區。
在本地運行以上代碼,java -version為:
openjdk version "1.7.0-internal"
OpenJDK Runtime Environment (build 1.7.0-internal- root_2016_09_18_14_57- b00)
OpenJDK 64-Bit Server VM (build 24.0-b56, mixed mode)
結果與書上相似:
用java -version為以下配置運行:
java version "1.7.0_111"
OpenJDK Runtime Environment (rhel-2.6.7.2.el7_2-x86_64 u111-b01)
OpenJDK 64-Bit Server VM (build 24.111-b01, mixed mode)
運行結果與上述一致。
Parallel Scavenge收集器
該收集器是一個新生代收集器,使用復制算法,并行多線程,吞吐量優先。
吞吐量 = 運行用戶代碼時間 / (運行用戶代碼時間 + 垃圾收集時間)
參數:
- -XX:MaxGCPauseMills 控制最大垃圾收集停頓時間
- -XX:GCTimeRatio 直接設置吞吐量大小
調小新生代大小 —> 垃圾收集頻繁 —> 縮短最大GC停頓時間 —> 增大了總的垃圾收集時間(收集次數*每次停頓時間)—> 降低吞吐量
當使用用java -version為1.7.0_79,且參數設置與上述一致時,運行結果為:
發現不發生Minor GC,并且新生代/老年代/永久代的名字變為PSYoungGen/ParOldGen/PSPermGen,認為是默認使用Parallel Scavenge收集器。
由于該收集器優先考慮吞吐量,有GC自適應調節策略來根據當前系統的運行情況動態調整新生代大小/Eden與Survivor區的比例/晉升老年代對象年齡等細節參數,通過-XX: +UseAdaptiveSizePolicy打開和關閉以上策略。
當沒有打開這個參數時,結果如上圖所示,allocation1-3占了新生代空間的91%,剩下的空間不足以放下4M的allocation4。
猜想:由于吞吐量優先,此時并不發生Minor GC,而是直接將allocation4放入老年代,減小吞吐量。
當打開這個參數之后,修改VM參數如下:
-verbose:gc -XX:+PrintGCDetails -XX:+UseAdaptiveSizePolicy -Xms20M -Xmx20M
運行后的結果為:
疑問1:GC后一個Survivor區使用了98%的空間,504K是放什么的?
疑問2:GC后老年代只放了4176K數據,allocation4去哪里了?
G1收集器
運作步驟:初始標記(標記GC Roots能直接關聯到的對象,停頓線程,耗時短) —> 并發標記(可達性分析,與用戶程序并發,耗時長) —> 最終標記(修正變動,停頓線程,可并行) —> 篩選回收(制定回收計劃,停頓線程)
分代收集:沒有永久代(待完善);
空間整合:整體:標記—整理,局部(Region間):復制;
可預測停頓。
大小相等的獨立區域Region集合組成新生代和老年代,期間無物理隔離。優先回收價值最大的Region,提高收集效率。
使用如下參數:
-verbose:gc -XX:+UseG1GC -XX:+PrintHeapAtGC -Xms20M -Xmx20M
則運行結果為:
今天先寫到這里。做實驗室的工作去了(。^▽^)
。。晚上要看《齊木楠雄的災難》。
參考:
- 《深入理解Java虛擬機:JVM高級特性與最佳實踐》 周志明
- 《G1 垃圾收集器入門 》http://blog.csdn.net/zhanggang807/article/details/45956325