JVM垃圾回收算法與垃圾收集器有哪些?

Jvm進行垃圾回收,首先需要判斷對象是否存活,那麼如何判斷對象是否存活呢?
當垃圾收集器在對堆進行回收前,第一就是要確定哪些對象還在被引用,或者後面還需要被引用(即存活態),哪些是已經“死去”(即不可能再被任何途徑使用),判斷對象是否存活主要用兩種算法,即引用計數算法和可達性分析算法。

判斷對象是否存活以後,Jvm主要通過4種垃圾回收算法進行垃圾回收,主要是:標記清除算法、複製算法、標記整理算法和分代回收算法。關於以上6種算法,會單獨以博客進行講解。

JVM虛擬機中有七個垃圾收集器,如圖(圖中連線的意思是這些垃圾收集器之間可以配合使用):

1)Serial收集器(採用複製算法收集新生代垃圾)
Serial是串行的意思,也就是說它以串行的方式執行,它是單線程的收集器,只會使用一個線程進行垃圾收集工作,GC線程工作時,其它所有線程都將停止工作。

所以,Serial收集器==新生代單線程收集器,標記和清理都是單線程,優點是簡單高效。在單個CPU環境下,由於沒有線程交互的開銷,所以擁有最高的單線程收集效率,所以,它是Client場景下的默認新生代收集器(是client級別默認的GC方式)。

2)ParNew收集器(採用複製算法收集新生代垃圾) 
可以認爲是Serial收集器的多線程版本,但要注意一點,ParNew在單核環境下是不如Serial的,在多核的條件下才有優勢。

Server場景下默認的新生代收集器,除了性能原因外,主要是因爲除了Serial收集器,只有它能與CMS收集器配合使用。

3)Parallel Scavenge收集器(採用複製算法收集新生代垃圾)
並行收集器,追求高吞吐量,高效利用CPU。同樣是多線程的收集器,其它收集器目標是儘可能縮短垃圾收集時用戶線程的停頓時間,而它的目標是提高吞吐量,吞吐量一般爲99%。

吞吐量=運行用戶程序的時間/(運行用戶程序的時間+垃圾收集的時間(GC線程時間))

停頓時間越短就越適合需要與用戶交互的程序,良好的響應速度能提升用戶體驗,所以高吞吐量適合對交互響應要求不高的場景,該收集器是server級別默認採用的GC方式,因爲高吞吐量可以高效利用CPU時間,儘快完成程序的運算任務。

4)G1收集器(使用複製+標記整理算法收集新生代和老年代垃圾)
G1(Garbage-First的縮寫)是一款面向服務端應用的垃圾收集器,在多CPU和大內存的場景下有很好的性能(使命是未來可以替換掉CMS收集器)。

G1把堆劃分成多個大小相等的獨立區域(Region),新生代和老年代不再物理隔離。

5)CMS收集器(採用標記清除算法收集老年代垃圾)
CMS(Concurrent Mark Sweep)收集器在JVM老年代收集器中佔據重要地位,其最大特點在於垃圾回收線程幾乎能做到與用戶線程同時工作,它的工作流程主要有4個步驟:
初始標記:僅僅只是標記一下GC Roots能直接關聯到的對象,速度很快,需要停頓(Stop-the-world)

併發標記:進行GC Roots Tracing的過程,它在整個回收過程中耗時最長,不需要停頓

重新標記:爲了修正併發標記期間因用戶程序繼續運作而導致標記產生變動的那一部分對象的標記記錄,需要停頓(Stop-the-world)

併發清除:清理垃圾,不需要停頓

在整個過程中耗時最長的併發標記和併發清除過程中,收集器線程都可以與用戶線程一起工作,不需要進行停頓。但CMS收集器也有如下缺點:
吞吐量低
無法處理浮動垃圾
標記清除算法帶來的內存空間碎片問題

6)Serial Old收集器(採用標記整理算法收集老年代垃圾)
與Serial收集器類似,不過Serial Old收集器只收集老年代,也是單線程收集器,是Client 場景下默認的老年代垃圾收集器

7)Parallel Old 收集器(採用標記整理算法收集老年代垃圾)
Parallel Scavenge收集器的老年代版本
在注重吞吐量的場景下,可以採用Parallel Scavenge + Parallel Old的組合

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章