上一節:《JVM之GC算法》 知道GC算法的理論基礎,咱們來看看具體的實現。只有落地的理論,纔是真理。html
JVM虛擬機規範對垃圾收集器應該如何實現沒有規定,由於沒有最好的垃圾收集器,只有最適合的場景。算法
圖中展現了7種做用於不一樣分代的收集器,若是兩個收集器之間存在連線,則說明它們能夠搭配使用。虛擬機所處的區域則表示它是屬於新生代仍是老年代收集器。多線程
7種:serial收集器、parnew收集器、parallel scavenge收集器、serial old 收集器、parallel old收集器、cms收集器、g1收集器(整堆收集器)、閉包
串行收集:單垃圾收集線程,進行收集工做,用戶進程須要等待併發
並行收集:工做原理與串行同樣,只是在收集垃圾時是多條線程同時進行,收集的效率在通常狀況下天然高於單線程。性能
併發收集:指用戶線程與垃圾收集線程同時工做(併發:同一時間間隔)。用戶程序在繼續運行,而垃圾收集程序運行在另外一個CPU上。spa
吞吐量:吞吐量就是CPU中用於運行用戶代碼的時間與CPU總消耗時間的比值(吞吐量 = 運行用戶代碼時間 / (運行用戶代碼時間 + 垃圾收集時間))線程
一、Serial收集器
Serial(串行)收集器:最基本,最古老的收集器,只有一個線程進行垃圾收集器的工做,而且在進行垃圾收集工做時須要暫停其餘工做線程(stop the word),直到他工做結束;
Serial收集器簡單高效,工做時沒有線程交互的開銷,因此能夠得到很高的單線程收集效率,對於運行在Client模式下的虛擬機來講很適合。htm
"-XX:+UseSerialGC":添加該參數來顯式的使用Serial垃圾收集器。對象
二、Serial Old收集器
Serial Old收集器是Seria收集器的老年代版本,他一樣是一個單線程收集器,使用" 標記-整理" 算法。
Serial Old收集器主要用於Client模式下的虛擬機使用。
Server模式下的兩大用途:
三、ParNew 收集器
ParNew(並行)收集器就是Serial收集器的多線程版本,除了在收集垃圾時是啓用多線程並行執行,其餘行爲(控制參數、收集算法、回收策略/Stop The Word、對象分配規則)徹底同樣
應用場景:ParNew收集器是許多運行在Server模式下的虛擬機中首選的新生代收集器,由於它是除了Serial收集器外,惟一一個能與CMS收集器配合工做的。
"-XX:+UseConcMarkSweepGC":指定使用CMS後,會默認使用ParNew做爲新生代收集器。
"-XX:+UseParNewGC":強制指定使用ParNew。
"-XX:ParallelGCThreads":指定垃圾收集的線程數量,ParNew默認開啓的收集線程與CPU的數量相同。
四、Parallel Scavenge收集器
Parallel Scavenge收集器 相似於 ParNew 收集器, Parallel Scavenge收集器 更加關注吞吐量(高效的CPU利用率)。CMS等垃圾收集器關注更多的是用戶線程的停頓時間(提搞用戶體驗);Parallel Scavenge 收集器提供不少參數供咱們找到最合適的停頓時間或者最大吞吐量。JDK1.8 默認的方式;
Parallel Scavenge收集器提供了兩個參數來用於精確控制吞吐量,一是控制最大垃圾收集停頓時間的 -XX:MaxGCPauseMillis參數,二是控制吞吐量大小的 -XX:GCTimeRatio參數;
應用場景:注重高吞吐量以及CPU資源敏感的場合,均可以優先考慮Parallel Scavenge+Parallel Old 收集器。
五、Paraller Old收集器
Parallel Old收集器是Parallel Scavenge收集器的老年代版本,使用多線程和「標記-整理」算法。
在JDK1.6中才出現。
六、CMS(Conturrent Mark Sweep)收集器
CMS收集器是一種以獲取最短回收停頓時間爲目標的收集器。CMS收集器是基於「標記-清除」算法實現,它的整個運行過程能夠分爲:
CMS收集器運行的整個過程當中,最耗費時間的是併發標記和併發清除,GC收集器線程和用戶線程是一塊兒工做的,因此整體來講,CMS收集器的內存回收過程是與用戶線程一塊兒併發執行的。
優勢:併發收集、低停頓。
缺點:
七、G1(Garbage-First)收集器
G1的內存模型
G1收集器沒有新生代和老年代的概念,而是將Java堆劃分爲一塊塊獨立的大小相等的Region。當要進行垃圾收集時,首先估計每一個Region中的垃圾數量,每次都從垃圾回收價值最大的Region開始回收,所以能夠得到最大的回收效率
Humongous是特殊的Old類型,專門放置大型對象.這樣的劃分方式意味着不須要一個連續的內存空間管理對象.G1將空間分爲多個區域,優先回收垃圾最多的區域.
G1採用的是Mark-Copy ,有很是好的空間整合能力,不會產生大量的空間碎片
G1的一大優點在於可預測的停頓時間,可以儘量快地在指定時間內完成垃圾回收任務,在JDK11中,已經將G1設爲默認垃圾回收器,經過jstat命令能夠查看垃圾回收狀況,在YGC時S0/S1並不會交換.
一個對象和它內部所引用的對象可能不在同一個Region中,那麼當垃圾回收時,是否須要掃描整個堆內存才能完整地進行一次可達性分析?
固然不是,每一個Region都有一個Remembered Set,用於記錄本區域中全部對象引用的對象所在的區域,從而在進行可達性分析時,只要在GC Roots中再加上Remembered Set便可防止對全部堆內存的遍歷.
回收步驟
初始標記:標記與GC Roots直接關聯的對象,中止全部用戶線程,只啓動一條初始標記線程,這個過程很快.
併發標記:進行全面的可達性分析,開啓一條併發標記線程與用戶線程並行執行.這個過程比較長.
最終標記:標記出併發標記過程當中用戶線程新產生的垃圾.中止全部用戶線程,並使用多條最終標記線程並行執行.
篩選回收:回收廢棄的對象.此時也須要中止一切用戶線程,並使用多條篩選回收線程並行執行.
G1爲何能創建可預測的停頓時間模型?
由於它有計劃的避免在整個Java堆中進行全區域的垃圾收集。G1跟蹤各個Region裏面的垃圾堆積的大小,在後臺維護一個優先列表,每次根據容許的收集時間,優先回收價值最大的Region。這樣就保證了在有限的時間內能夠獲取儘量高的收集效率。
G1與其餘收集器的區別?
其餘收集器的工做範圍是整個新生代或者老年代、G1收集器的工做範圍是整個Java堆。在使用G1收集器時,它將整個Java堆劃分爲多個大小相等的獨立區域(Region)。雖然也保留了新生代、老年代的概念,但新生代和老年代再也不是相互隔離的,他們都是一部分Region(不須要連續)的集合。
一、單CPU或者小內存,單機程序 — -XX:+UseSerialGC
二、多CPU,須要大吞吐量,如後臺計算型應用,容許工做線程停頓超過1秒 -XX:+UseParallelGC + -XX:+UseParallelOldGC
三、多CPU,追求低停頓時間,快速響應如互聯網應用 -XX:+UseParNewGC + -XX:+UseConcMarkSweepGC
四、JVM本身選擇
五、官方推薦G1,高性能