天天看點

Java垃圾收集器

如果說收集算法是記憶體回收的方法論,那麼垃圾收集器就是記憶體回收的具體實作。

雖然我們在對各種收集器進行比較,但是并非為了挑出一個最好的收集器。因為直到現在為止還沒有最好的收集器出現,更加沒有萬能的收集器,是以我們選擇的隻是對具體應用最合适的收集器。

1.Serial收集器(串行收集器)

這個收集器是一個單線程的收集器,但是它的單線程的意義并不僅僅說明它隻會使用一個CPU或一條收集線程去完成垃圾收集工作,更重要的是在它進行垃圾收集時,必須暫停其他所有的線程(Stop-The-World:将使用者正常工作的線程全部暫停掉),直到它收集結束。收集器的運作過程如下圖所示:

Java垃圾收集器

上圖中:

新生代采用複制算法,Stop-The-World

老年代采用标記-整理算法:Stop-The-World

當他進行GC工作的時候,雖然會造成Stop-The-World,但是它存在有存在的原因:正是因為他的簡單而高效(與其他收集器的單線程比),對于限定單個CPU的環境來說,沒有現成互動的開始,專心做GC,自然可以獲得最高的單線程收集效率。是以Serial收集器對于運作在client模式下是一個很好的選擇(它依然是虛拟機運作在client模式下的預設新生代收集器)。

2.ParNew收集器

Serial收集器的多線程版本(使用多條線程進行GC)

它是運作在server模式下的首選新生代收集器,除了Serial收集器外,目前隻有它能與CMS收集器配合工作。CMS收集器是一個被認為具有時代意義的并發收集器,是以如果有一個垃圾收集器能和它配合一起使用更加完美,那這個收集器必然也是一個不可或缺的部分了。收集器的運作過程如下圖所示:

Java垃圾收集器

新生代采用複制算法:Stop-The-World

3.Parallel Scavenge收集器

類似ParNew,但更加關注吞吐量。目标是:達到一個可控制吞吐量的收集器。

停頓時間和吞吐量不可能同時調優。我們一方面希望停頓時間少,另一方面希望吞吐量高。其實這是沖突的,因為:在GC的時候,垃圾回收的工作總量是不變的,如果将停頓時間減少,那麼頻率就會提高;頻率提高說明會頻繁的進行GC,那吞吐量就會減少,性能就會降低。

吞吐量:CPU用于使用者代碼的時間/CPU總消耗時間的比值。即=運作使用者代碼的時間/(運作使用者代碼時間+垃圾收集時間)。比如,虛拟機總共運作了100分鐘,其中垃圾收集花掉1分鐘,那吞吐量就是99%

4.G1收集器

是當今收集器發展的最前沿成果之一,直到JDK1.7,SUN公司才認為它達到了足夠成熟的商用程度。

優點:

它最大的優點是結合了空間整合,不會産生大量的碎片,也降低了進行GC的頻率。

二是可以讓使用者明确指定停頓時間,(可以指定一個最小時間,超過這個時間,就不會進行回收了)

它有了這麼高效率的原因之一就是:對垃圾回收進行了劃分優先級的操作,這種有優先級的區域回收方式保證了它的高效率。

如果你的應用追求停頓,那G1現在已經可以作為一個可以嘗試的選擇,如果你的應用追求吞吐量,那G1并不會為你帶來什麼特别的好處。

注意:以上所有的收集器當中,當執行GC是,都會Stop-The-World,但是下面的CMS收集器卻不會這樣。

5.CMS收集器(老年代收集器)

CMS收集器(Concurrent Mark Sweep:并發标記清除)是一種以擷取最短回收停頓時間為目标的收集器。适合應用在網際網路站或者B/S系統的伺服器上,這類應用尤其總是伺服器的響應速度,希望系統停頓時間最短。

CMS收集器運作過程:(着重實作了标記的過程)

(1)初始标記

根可以直接關聯到對象

速度快

(2)并發标記(和使用者線程一起)

主要标記過程,标記全部對象

(3)重新标記

由于并發标記時,使用者線程依然運作,是以在正式清理前,再做修正。

(4)并發清除(和使用者線程一起)

整個過程如下圖所示:

Java垃圾收集器

上圖中,出現标記和重新标記時,需要Stop-The-world.整個過程中耗時最長的是并發标記和并發清除,這兩個過程都可以和使用者線程一起工作。

并發收集,低停頓。

缺點:

(1)導緻使用者執行速度降低。

(2)無法處理浮動垃圾,因為它采用的是标記-清除算法,有可能有些垃圾在标記之後,需要等到下一次GC才會被回收。如果CMS運作期間無法滿足程式需要,那麼就會臨時啟用Serial Old收集器來重新進行老年代的收集。

(3)由于采用的是标記-清除算法,那麼就會産生大量的碎片。往往會出現老年代還有很大的空間剩餘,但是無法找到足夠大的連續空間來配置設定目前對象,不得不提前出發一次Full GC

疑問:既然标記-清除算法會造成記憶體空間的碎片化,CMS收集器為什麼使用标記清除算法而不是标記整理算法?

答:CMS收集器更加關注停頓,它做GC的時候是和使用者線程一起工作的(并發執行),如果使用标記整理算法的話,那麼清理的時候就會去移動可用對象的記憶體空間,那麼應用程式的線程就很有可能找不到應用對象在哪裡。

6.Serial Old收集器

Serial Old是Serial收集器的老年代版本,使用“标記-整理”算法。這個收集器的主要意義也是在于給Client模式下的虛拟機使用。如果在Server模式下,那麼它主要還有兩大用途:一種用途是在JDK1.5以及之前的版本中與Parallel Scavenge收集器搭配使用。另一種用途就是作為CMS收集器的後備預案,在并發收集發生Concurrent Mode Failure時使用。

7.Parallel Old收集器

心再堅強也不要獨自飛翔

繼續閱讀