title: JVM學習筆記——垃圾收集器
date: 2018/9/4 17:09:31
description: 最近開始著手JVM的學習,在這裡把自己學習過程中的筆記分享出來,希望能幫到一些小夥伴,同時也是對自己的學習的一個梳理。
垃圾收集器
垃圾收集器內容頗多,但演算法原理都是基於垃圾收集演算法,故這裡只簡單介紹一下各收集器的特點。
- HopSpot中的收集器群
兩個虛擬機器之間的連線表示它們可以搭配使用,反之則不能搭配。
- Serial收集器
- 使用“標記-整理”演算法
- “單線程”收集器,這裡的單線程指的是Serial在對某一條線程執行收集工作時,必須暫停其他線程的運行,這就會造成大量的GC停頓出現。
- 優點是簡單高效,在Client模式的虛擬機器中表現優秀。
- Serial Old收集器
- Serial的老年代版本,特性基本與Serial一致。
- 在JDK1.5之前可以與Parallel搭配使用,或者作為CMS的後備方案。
- ParNew收集器
- ParNew就是針對Serial改進的多線程版本。
- 在很多虛擬機器中,ParNew卻是新生代的首選收集器,因為除了Serial只有它能夠與CMS搭配使用。
- Parallel Scavenge收集器
- 是一個新生代的收集器,使用多線程+複製演算法。
- 主要關注輸送量的收集器
輸送量=運行使用者代碼時間/(運行使用者代碼時間+垃圾收集時間),提供兩個參數用於精確控制輸送量:
- -XX:MaxGCPauseMillis,最大GC停頓時間。允許的值是一個大於0的毫秒數,收集器儘可能保證收集時間不超過該值。注意,停頓時間縮短需要犧牲輸送量和空間,更小的停頓時間可能會導致更頻繁的GC。
- -XX:GCTimeRatio,GC時間佔總時間比率。是一個0-100之間的整數,等於輸送量的倒數。
- Parallel Old收集器
- Parallel Scavenge的老年代版本,使用多線程+標記整理演算法。
- 由於Serial Old在服務端上效能不佳,故有了該收集器與Parallel Scavenge進行搭配使用。
- CMS收集器(Concurrent Mark Sweep)
- 基於標記-清除演算法實現,是一款以擷取最短GC停頓時間為目標的收集器。它的運作過程分為4步:
- 初始標記
標記GC Roots能關聯到的對象。
- 並發標記
由GC Roots發起對象的跟蹤,驗證是否可達。
- 重新標記
修正並發標記期間變動的一部分對象的標記記錄。
- 並發清除
清除標記對象的空間。
其中只有初始標記與重新標記兩個過程需要進行停頓,但是這兩個過程僅僅是標記,速度很快,最漫長的清除過程在CMS下可以與使用者線程平行處理。
- CMS雖然很強大,但還是有著以下3個缺點:
- 雖然CMS不會導致GC停頓,但並發的代價就是會佔用CPU資源,可能會導致使用者程式變慢,在核心數較低的CPU中該問題會越發明顯。
- 由於CMS的清理不會暫停使用者線程,可能導致“浮動垃圾”的出現,那就需要留出一部分記憶體空間對應“浮動垃圾”,所以CMS有一個觸發回收的記憶體比例,在JDK1.6中該值預設為92%。如果預留的記憶體還是無法滿足程式需求,CMS就會啟動備用方案(一般是Serial Old)來重新進行收集。
- 由於CMS使用的是標記-清除演算法,所以會有大量的記憶體片段產生,會導致大對象找不到空間存放而提前觸發一次Full GC進行記憶體整理。
- G1收集器在JDK1.7之後才出現的收集器,G1具備以下四個特點:
- 並行與並發,能利用多線程,多CPU的優勢,使得GC與使用者線程並行。
- G1能夠獨自對整個GC堆進行管理,並且留有了分代的特性,可以根據不同的地區採用不同的方式處理。
- 將Java堆劃分為多個大小相等的獨立地區(Region),在Region上來看是基於複製演算法實現的,從整體上看是基於標記-整理演算法實現,結合了兩種演算法的優點。
- 建立了可預測的停頓模型,可以通過
-XX:MaxGCPauseMillis來設定期望GC時間,G1會盡量在該時間內完成GC。