本來這一篇應該是和大家分享以下HotSpot的算法實現的,但是有部分內容存在一些疑問,還需進一步研究一下,今天就簡單介紹一下幾種不同的垃圾收集器。
開始之前有幾點需要提前介紹一下。
第一點,書中提到了一個詞,“Stop The World”——即當進行垃圾收集的時候,必須暫停其它所有的工作線程。
第二點,Java的HotSpot虛擬機有兩種工作模式,Client模式(輕量級)和Server模式(重量級)。
可以通過在cmd中輸入命令java -version進行查看。
第三點,這個要注意啦!!!在討論垃圾收集器的時候,併發和並行的概念。
併發:傳統意義上併發是隻一個時間段內多個線程或進程同時執行(時間片輪流調度),但是時間點上只有一個在執行。
在這裏,指用戶線程和垃圾收集線程同時執行,分別在不同的CPU中。
並行:傳統意義上並行是不光一個時間段內多個線程或進程同時執行,時間點上也有多個線程或進程在執行(多核CPU)。
在這裏,指的是多條垃圾收集線程並行工作,但用戶線程處於暫停狀態。
知道了這幾個概念之後,下面簡單介紹一下這七種垃圾收集器。
1 Serial收集器:最基本,發展歷史最久遠的收集器。
採用單線程的工作方式,會“Stop The World”,適用於Client模式下虛擬機。
優點:和其它單線程的相比,不存在併發,沒有線程切換的開銷,簡單而高效。
2 ParNew收集器:Serial的多線程版本,使用多線程並行進行垃圾收集,並且是併發的,不存在“Stop The World”;適用於Client模式下虛擬機。
3 Parallel Scavenge收集器:也是並行多線程的,與其它的收集器的不用之處在於,Parallel Scavenge收集器關注的是控制吞吐量。可以通過調整參數,控制停頓時間或最大的吞吐量(自適應調節策略)。
吞吐量=運行用戶代碼時間/(運行用戶代碼時間+垃圾收集時間)
提高吞吐量可以提高CPU的利用率,適合在後臺運算而不需要太多交互的任務(什麼鬼)?
4 Serial Old收集器:Serial收集器的老年代版本,也是單線程的。
5 Parallel Old收集器:Parallel Scavenge收集器的老年代版本。
6 CMS(Concurrent Mark-Sweep)收集器:爲了滿足B/S項目響應速度的要求,以獲取最短回收停頓時間爲目標;可併發收集但是仍然會出現“Stop The World”。
7 G1收集器:當前收集器技術發展最前沿的技術之一;面向服務端應用;
特點:並行+併發;分代收集;空間整合;可預測的停頓;
具體的詳情可以對照下表。
另附各收集器之間的組合使用圖(圖片參照《深入理解JAVA虛擬機》)
GC日誌:這裏只要記住日誌內容每一項代表的規則就可以了。
舉個例子,使用IDEA編寫如下代碼
以前介紹過如何設置idea的JVM參數,這裏直接在debug中進行配置,增加打印詳細日誌參數-XX:+PrintGCDetails
點擊debug運行程序,控制檯打印如下內容。下面讓我們一次進行分析。
1. GC日誌開頭的“[GC”和“[Full GC”說明了這次垃圾收集的停頓類型,如果有”Full”,說明這次GC發生了”Stop-The-World”;
2. 緊跟着括號內的“System.gc()”表示本次回收的觸發方式;
3. 接下來的“[PSYoungGen”,“[ParOldGen”,“[Metaspace”表示GC發生的區域;
4. 方括號裏面的“6856K->0K(76288K)”,“8K->6717K(175104K)”等表示的是“GC前該內存區域已使用的容量->GC後該內存區域已使用的容量(該內存區域總容量)”;
5. 方括號外面的“6864K->6717K(251392K)”表示“GC前Java堆已使用容量->GC後Java堆已使用容量(Java堆總容量)”;
6. 再往後的“0.0054064 secs”表示的是內存區域GC所佔用的時間,單位是秒;
7. 最後面的“[Times: user=0.06 sys=0.00, real=0.01 secs]”是更具體的時間,分別代表用戶態消耗的CPU時間,內核態消耗的CPU時間,操作從開始到結束所用的時鐘時間;
8. 書中介紹開頭時候還會有如“33.125:”樣式的GC發生時間,記錄的是從Java虛擬機啓動以來經過的秒數,筆者使用的JDK8是沒有顯示的。
喜歡文章或想一起學習的朋友可以關注我,我將會持續更新,有什麼疑問或文中有不當之處請給我留言,真誠地希望能與大家一起交流探討,學習進步。