CMS GC發生concurrent mode failure時,為什麼使用單線程的full GC?
最近看了一些JVM調優、垃圾收集方面的書和文章,在full GC的處理上有一些疑問,為什麼當併發模式失敗之後,會退化到單線程的full GC,而不使用並行的full GC呢,不應該是並行的full GC更快一些嗎?請各位大神幫忙解答
先說結論:因為沒足夠開發資源,偷懶了。就這麼簡單。沒有任何技術上的問題。
事實上,還在大量使用CMS GC的公司各自有過若干嘗試,把CMS GC配套的備份full GC改進為並行的。
阿里巴巴的Ali JDK做了,Google內部使用的OpenJDK也做了。
Twitter據說也對CMS GC做了一些優化,不知道他們有沒有也自己做過配套備份full GC的並行化;Twitter JDK很快就要開源了,到時候看看就知道。
相關鏈接:
- RFR (XL): JDK-8086706 Parallel Full GC for CMS
- JDK-8130200: Parallelize the Full GC Phase in CMS
- RFR: JEP: Parallelize the Full GC Phase in CMS
- patch:http://cr.openjdk.java.net/~jwha/8086706/webrev.jdk9.00/
所以最初怎麼會偷這個懶的呢?
多災多難的CMS GC經歷了多次動蕩。它最初是作為Sun Labs的Exact VM的低延遲GC而設計實現的。但Exact VM在與HotSpot VM爭搶Sun的正牌JVM的內部鬥爭中失利,CMS GC後來就作為Exact VM的技術遺產被移植到了HotSpot VM上。
就在這個移植還在進行中的時候,Sun已經開始略顯疲態;到CMS GC完全移植到HotSpot VM的時候,Sun已經處於快要不行的階段了。開發資源減少,開發人員流失,當時的HotSpot VM開發組能夠做的事情並不多,只能挑重要的來做。
而這個時候Sun Labs的另一個GC實現,Garbage-First GC(G1 GC)已經面世。相比可能在長時間運行後受碎片化影響的CMS,G1會增量式的整理/壓縮堆里的數據,避免受碎片化影響,因而被認為更具潛力。於是當時本來就不多的開發資源,一部分還投給了把G1 GC產品化的項目上——結果也是進展緩慢,畢竟只有一兩個人在做。
所以當時就沒能有足夠開發資源去打磨CMS GC的各種配套設施的細節,配套的備份full GC的並行化也就耽擱了下來。
但肯定會有同學抱有疑問:HotSpot VM不是已經有並行GC了么?而且還有好幾個?讓我們來看看:- ParNew:並行的young gen GC,不負責收集old gen
- Parallel GC(ParallelScavenge):並行的young gen GC,與ParNew相似但不兼容;同樣不負責收集old gen
- ParallelOld GC(PSCompact):並行的full GC,但與ParNew / CMS不兼容
所以…就是這麼一回事。HotSpot VM確實是已經有並行GC了,但兩個是只負責在young GC時收集young gen的,這倆之中還只有ParNew能跟CMS搭配使用;而並行full GC雖然有一個ParallelOld,但卻與CMS GC不兼容所以無法作為它的備份full GC使用。
這不兼容又是怎麼回事?就不多碼字了,感興趣的同學請跳傳送門:ParNew 和 PSYoungGen 和 DefNew 是一個東西么?
推薦閱讀:
TAG:Java虛擬機JVM | GC垃圾回收計算機科學 | HotSpotVM |
