0. 預備知識
0.1 Stop-the-World
- JVM 由於要執行 GC 而停止了程式的執行
- 這種情況會在任何一種 GC 演算法中發生
- 多數 GC 優化通過減少 Stop-the-World 發生的時間來提高程式效能
0.2 Safepoint
在可達性分析中,將所有執行緒都停止,形成一個快照點 (Safepoint),保證了分析結果的確定性
- 產生 Safepoint 的地方:方法呼叫、迴圈跳轉和異常跳轉等
- Safepoint 數量要適中
0.3 JVM 執行模式
- Server
- Client
Server 啟動較慢,但是啟動之後的執行速度比 Client 更快
# 檢視 JVM 使用哪種執行模式
$ java -version
java version "1.8.0_221"
Java(TM) SE Runtime Environment (build 1.8.0_221-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.221-b11, mixed mode)
複製程式碼
1. 常見垃圾收集器
1.1 年輕代中常見垃圾收集器
1.1.1 Serial 收集器
- 單執行緒收集,進行垃圾收集時,會暫停所有工作執行緒
# 指定 GC 使用 Serial (複製演算法)
-XX: +UseSerialGC
複製程式碼
1.1.2 ParNew 收集器
- 多執行緒收集,其餘與 Serial 一致
- 單核執行效率不如 Serial,多核下有優勢
# 指定 GC 使用 ParNew (複製演算法)
-XX: +UseParNewGC
複製程式碼
1.1.3 Parallel Scavenge 收集器
吞吐量 = 執行使用者程式碼的時間 / (執行使用者程式碼的時間 + 垃圾回收的時間)
- 與 ParNew 類似,都使用多執行緒
- Parallel Scavenge 相對於 ParNew 不同的是,後者更注意使用者執行緒的等待時間,前者則是關注整個系統的吞吐量
- JVM Server 模式下預設
# 指定 GC 使用 Parallel Scavenge (複製演算法)
-XX: +UseParallelGC
複製程式碼
1.2 常見的老年代收集器
1.2.1 Serial Old 收集器
- 單執行緒收集,進行垃圾收集時,會暫停所有工作執行緒
- 簡單高效,Client 模式下預設的老年代收集器
# 指定 GC 使用 Serial Old (標記-整理演算法)
-XX: +UseSerialOldGC
複製程式碼
1.2.2 Parallel Old 收集器
- 與 Parallel Scavenge 類似,只不過採用的是標記-整理演算法
# 指定 GC 使用 Parallel Old (標記-整理演算法)
-XX: +UseParallelOldGC
複製程式碼
1.2.3 CMS 收集器
- 清理執行緒和使用者執行緒幾乎能做到同時工作
標記和回收過程 (六步)
- 初始標記:Stop-the-World
- 併發標記:併發追溯標記,程式不會停頓
- 併發預清理:查詢執行併發標記階段從年輕代晉升到老年代的物件
- 重新標記:暫停虛擬機器 (Stop-the-World),掃描 CMS 堆中的剩餘物件
- 併發清理:清理垃圾物件,程式不會停頓
- 併發重置:重置 CMS 收集器的資料結構
# 指定 GC 使用 CMS (標記-清除演算法)
-XX: +UseConcMarkSweepGC
複製程式碼
1.3 年輕代和老年代公用的演算法
1.3.1 G1 收集器
- 併發和並行
- 分代收集
- 空間整合(標記-整理)
- 可預測的停頓(指定在 M 毫秒內,消耗在 GC 上的時間不得超過 N 毫秒)
工作原理簡述
- 將 Java 堆記憶體劃分成多個大小相等的 Region
- 上面的特性導致了,新生代和老年代不再是物理隔離的記憶體空間,他們現在都是一系列 Region 的集合,在邏輯上連續
# 指定 GC 使用 G1 (複製 + 標記-清除演算法)
-XX: +UseG1GC
複製程式碼