Java常用的垃圾回收器
Java常用的垃圾回收器組合:
1. Serial GC
使用:-XX:+UseSerialGC
Serial GC 是新生代的垃圾回收器,Serial 體現在其收集工作是單執行緒的,並且在垃圾收集過程中,其他執行緒阻塞,進入 Stop the World 狀態。新生代使用 Serial 垃圾回收器,是基於複製演算法的。
2. Parallel Scavenge
使用:-XX:+UseParallelGC
Parallel Scavenge 收集器是一個新生代的垃圾回收器,採用的是複製演算法。關注的是程式到達一個可控制的吞吐量(CPU 用於執行使用者程式碼的時間 / CPU總消耗時間)。吞吐量 = 執行使用者程式碼時間 / (執行使用者程式碼時間 + 垃圾收集時間)。高吞吐量可以最高效率的利用 CPU 時間,儘快完成程式的運算任務。
其中:
Parallel Scavenge 收集器有個自適應調節引數。這個引數是:-XX:UseAdaptiveSizePolic。這是一個開關引數,當這個開關開啟後,就不需要手動指定新生代的大小(-Xmn)、Eden 和 Survivor 區的比例(-XX:SurvivorRatio)、晉升老年代物件大小(-XX:PertenureSizeThreshold)等引數細節了,虛擬機器會根據當前系統的執行情況收集效能監控資訊,動態調整這些引數以提供最合適的停頓時間或者最大的吞吐量。
可以直接設定暫停時間或者吞吐量等目標,JVM 會自動進行適應性調整。
-XX:MaxGCPauseMillis=
-XX:GCTimeRatio=N // GC時間和使用者時間比例 = 1 / (N+1)
3. ParNew
使用:-XX:+UseParNewGC
ParNew 垃圾回收器是 Serial 收集器的多執行緒版本。採用的也是複製演算法。包括 Serial 收集器可用的所有控制引數。也就是可並行的進行垃圾回收。
可通過 -XX:ParallelGCThreads 引數來限制垃圾收集器的執行緒數。
4. Serial Old
Serial Old 是 Serial 垃圾收集器的老年代版本,同樣是個單執行緒的收集器,是基於 標記-整理演算法。
5. Parallel Old
Parallel Old 是 Parallel Scavenge 的老年代版本,使用的是 多執行緒-標記整理演算法。JDK1.6 才開始使用。Parallel Scavenge 是可以保證新生代的吞吐量優先,但是不能保證整體吞吐量。Parallel Old 是為了在老年代同樣提供吞吐量優先的垃圾回收器。
6. CMS
使用:-XX:+UseConcMarkSweepGC
CMS 是基於標記清除演算法,設計的目的是減少停頓時間。基於標記清除演算法,會存在記憶體碎片化的問題。其處理流程:
1)初始標記(CMS-initial-mark),會導致 stw;
2)併發標記(CMS-concurrent-mark),與使用者執行緒同時執行;
3)重新標記(CMS-remark),會導致 stw;
4)併發清除(CMS-concurrent-sweep),與使用者執行緒同時執行;
5)併發重置狀態等待下次 CMS 的觸發(CMS-concurrent-reset),與使用者執行緒同時執行;
7. G1
G1 本質上是一個分代垃圾回收器。G1 垃圾回收器相對於 CMS 垃圾回收器,有兩個改進:
1)基於標記-整理演算法,不產生記憶體碎片
2)可以準確的控制停頓時間,在不犧牲吞吐量的情況下實現低停頓的垃圾回收
G1 為了避免全域的垃圾收集,把堆記憶體劃分成大小固定的幾個獨立區域,並跟蹤這些區域的回收進度。同時在後臺維護一個優先列表,每次根據收集時間,優先回收垃圾最多的區域。
G1 引入了額外的概念,Region。G1 垃圾回收器把堆劃分一個個大小相同的 Region。在 HotSpot 的實現中,整個堆被劃分成 2048 左右個的 Region。每個 Region 的大小在 1-32M 之間,具體的大小取決於堆得大小。
G1 垃圾回收器的分代也是建立在這些 Region 的基礎上的。對於 Region 來說,他會有一個分代的型別,並且是唯一一個。即:每一個 Region,它要麼是 yong 的,要麼是 old 的。還有一類十分特殊的 Humongous。所謂的 Humongous,就是一個物件的大小超了某一閾值 —— HotSpot中是 Region 的 1/2 ,那麼它會被標記為 Humongous。如果我們審視 HotSpot 的其餘的垃圾回收器,可以發現,這種物件以前被稱為大物件,會被直接分配老年代。而在 G1 回收器中,則是做了特殊的處理。
G1 並不要求相同型別的 region 要相鄰。換言之,就是 G1 回收器不要求他們連續。當然在邏輯上,分代依舊是連續的。
每一個分配的 Region,都可以分成兩個部分,已分配的和未分配的。他們之間的界限被稱為 top。把一個物件分配到 Region 內,只需要簡單的增加 top 的值。這個做法實際上就是 bump-the-pointer。過程如下:(移動 top 線)
Region 是 G1 回收器一次回收的最小單元,即每一次回收都是回收 N個 Region。這個 N 是多少,主要受到 G1 回收效率和使用者設定的軟實時目標有關。每一次的回收,G1 會選擇可能回收最多垃圾的 Region 進行回收。與此同時,G1 回收器會維護一個空間 Region 的連結串列。每次回收後的 Region 都會被加入這個連結串列。每一次都只有一個 Region 處於被分配的狀態中,被稱為 current region 。在多執行緒的情況下會帶來併發問題。G1 回收器採用和 CMS 一樣的 TLABs 的手段,即為每一個執行緒分配一個 buffer,執行緒分配記憶體就在這個 buffer 內分配,但是當執行緒耗盡了自己的 buffer 以後,需要重新申請新的 buffer。這個時候依然會帶來併發的問題。G1 回收器採用的是 CAS 操作。
注:以上為學習摘抄做的筆記。