上一章我們已經探討過GC的各個演算法,那麼垃圾蒐集器是什麼呢?
通俗的講,使用程式語言將演算法實作出來,產生的程式就是垃圾蒐集器了。既然談到了程式語言的實現,那麼在討論垃圾蒐集器的時候,就已經涉及到具體的虛擬機器實現了。
或許有不少做JAVA開發的猿友還不知道,我們平時使用的JDK中,預設的JVM是hotspot,換句話說,我們大部分時候使用的JVM都是hotspot的實現版本,因此,本次LZ討論垃圾蒐集器都是基於hotspot版JVM來進行的,請各位猿友要知曉這一點。
更直覺的,我們可以在我們平常開發的機子上,輸入java -version來查看JVM的版本,相信大部分猿友對這個命令都不陌生吧,LZ的機子截圖如下。
垃圾蒐集器的分類
上面我們已經提到,垃圾蒐集器實際上就是演算法的程式語言實作。既然牽扯到程式語言,那麼必然離不開線程,而且我們在前面講解演算法的時候也一直假設是一條GC線程在做著GC的事情。
因此,垃圾蒐集器大致分為以下三類。
串列蒐集器(serial collector):它只有一條GC線程,而且就像前面說的,它在運行的時候需要暫停使用者程式(stop the world)。
並行蒐集器(parallel collector):它有多條GC線程,而且它也需要暫停使用者程式(stop the world)。
並發蒐集器(concurrent collector):它有一條或多條GC線程,且它需要在部分階段暫停使用者程式(stop the world),部分階段與使用者程式並發執行。
看完上面的定義,相信有一部分猿友已經蒙了,一會兒單線程,一會多線程,一會串行,一會並行,一會兒並發,這都神馬玩意?
單執行緒與多執行緒就不必多說了,這個很好理解,串列與並行也比較好理解,難於分辨的就是並行(parallel)與並行(concurrent)。
對於許多有關並發的解釋,LZ覺得有一個最貼切。它是這麼解釋的,並發就是兩個任務A和B需要相互獨立的運行,A任務先開始後,B任務在A任務結束前就開始了。
並發本身是比較好理解的,那麼它與並行的關係與區別是什麼呢?
事實上,並行是並發的一種實現方式。 LZ覺得這麼說各位可能會更好理解,當然,並行並不是並發的唯一實現方式,還有一種就是我們所熟悉的時間片切換。也就是A任務執行一會,B任務執行一會,交替執行。
並行必須在多核心多處理器或分散式系統(本質還是多核心多處理器)的前提下才能發生,而交替執行或說時間片切換是在單核心的處理器上發生的。
hotspot中的垃圾蒐集器
我們上面已經簡單探討了垃圾蒐集器的分類,在hotspotJVM中,每一個種類的垃圾蒐集器都有對應的實現,如下。
串列蒐集器的實現:serial(用於新生代,採用複製演算法)、serial old(用於年老代,採用標記/整理演算法)
並行蒐集器的實作:ParNew(用於新生代,採用複製演算法)、Parallel Scavenge(用於新生代,採用複製演算法)、Parallel old(用於年老代,採用標記/整理演算法)
並發蒐集器的實作:concurrent mark sweep[CMS](用於年老世代,採用標記/清除演算法)
可以看到,上面每一種垃圾蒐集器都是針對不同記憶體區域所設計的,因為它們採用的演算法不同,凡是用於新生代的都是使用的複製演算法,而用於年老代的都是使用的標記/清除或標記/整理演算法。
在實際應用中,我們需要給JVM的新生代和年老代分別選擇垃圾蒐集器,可以看到無論是新生代還是年老代都分別有三種實現,換句話說,我們應該有3*3 =9種選擇。但是,事實並非如此。
事實上,這六種垃圾蒐集器只有六種選擇,因為有的垃圾蒐集器由於具體實現的方式等一系列原因無法在一起工作,如下圖。
針對上圖,紅的就是串列蒐集器,綠的是平行蒐集器,唯一一個黃的是並發蒐集器。上面三個是新生代的蒐集器,下面三個是年老代的蒐集器。兩者之間有連線,則表示兩者可以配合工作。
這六種組合並沒有說哪個組合最強,哪個組合最弱,還是那句話,只有最合適的,沒有最好的。因此這就需要我們對每一種組合有一定的認識,才能在使用的時候選擇更適合的垃圾蒐集器。
結束語
以上就是JVM記憶體管理------垃圾蒐集器簡介的內容,更多相關內容請關注PHP中文網(www.php.cn)!