Java新型垃圾回收器G1深入探索
G1垃圾回收器
“G1垃圾回收”的英文全稱是 Garbage-First Garbage Collector (又被稱作G1 GC),這是一個(gè)新型的垃圾回收器,由JDK 7中的Java HotSpot VM 引入。這個(gè)技術(shù)曾經(jīng)在Java SE 6 Update 14版本中出現(xiàn)過(guò)一個(gè)試驗(yàn)性的,然后 G1 被 HotSpot的 反應(yīng)快速(low-latency)的 Concurrent Mark-Sweep GC (簡(jiǎn)稱 CMS)長(zhǎng)期取代。
屬性
G1 是一個(gè)“服務(wù)器風(fēng)格(server-style)”的垃圾回收器,它主要有下面的這些屬性:
◆并行和并發(fā)。 G1 可以從今天最新的硬件中獲得并行的能力。它能夠使用所有可用的CPU(CPU多核,硬件多線程,等)來(lái)加速它的 “stop-the-world” 機(jī)制(這個(gè)機(jī)制簡(jiǎn)稱STW,即,在執(zhí)行垃圾收集算法時(shí),Java應(yīng)用程序的其他所有除了垃圾收集幫助器線程之外的線程都被掛起)。
◆分代處理。 就像其它的HotSpot 垃圾回收器,G1 是分代的,也就是說(shuō),它在處理新分配的對(duì)象(年輕代)和已經(jīng)生存了一段時(shí)間的對(duì)象(年老代)時(shí)會(huì)不同,它會(huì)更多地考慮一些新創(chuàng)建的對(duì)象實(shí)例,因?yàn)樵叫聞?chuàng)建的就越有最大的可能性被回收,老對(duì)象只是偶爾訪問(wèn)一下。對(duì)于大多數(shù)的Java應(yīng)用來(lái)說(shuō),這個(gè)機(jī)制可以極大地提高回收效率。
◆緊湊內(nèi)存(碎片整理)。 不像CMS,G1 會(huì)對(duì)堆進(jìn)行內(nèi)存整理。壓縮可以消除潛在的內(nèi)存碎片的問(wèn)題,這樣程序就可以更長(zhǎng)時(shí)間的平滑運(yùn)行。
◆預(yù)見(jiàn)性的。 G1 比起 CMS 來(lái)有更多的預(yù)見(jiàn)性。這個(gè)主要還是用來(lái)消除內(nèi)存碎片的問(wèn)題。內(nèi)存的碎片少了,Stop-the-World的暫停時(shí)間也會(huì)被減少。
描述
比起其它的HotSpot 垃圾回收器來(lái)說(shuō),G1 使用了一種非常不同尋常的方法來(lái)管理堆內(nèi)存的布局。在G1中,在對(duì)象新生代和老一代上沒(méi)有在物理上把他們分隔開來(lái)。取而代之的是,它把一個(gè)連續(xù)的堆內(nèi)存拆分成了幾個(gè)相同大小的區(qū)域。新產(chǎn)生的對(duì)象和老的對(duì)象都會(huì)被放在一系列可能不會(huì)連續(xù)的區(qū)域中。之所以這樣做,就是為了讓G1可以更靈活地移動(dòng)老對(duì)象所占用的資源給新的對(duì)象。
G1中的內(nèi)存收集會(huì)發(fā)生 “疏散暫?!?,當(dāng)內(nèi)存從一系例區(qū)域開始回收時(shí),這些區(qū)域所引用的 collection set 會(huì)被疏散到另一些區(qū)域中,這樣,我們會(huì)有一整塊的內(nèi)存來(lái)重新被申請(qǐng)。疏散會(huì)發(fā)生整個(gè)程序的暫停,但“疏散”這些內(nèi)存可以被并行運(yùn)行,當(dāng)然,你要有多核或多線程技術(shù)來(lái)支持。絕大多數(shù)的“疏散暫停”會(huì)去收集那些可用的比較新的內(nèi)存區(qū)域,因此,這和其它的 HotSpot 垃圾回收器是相同的。偶而才會(huì)去查看一下老區(qū)域中的內(nèi)存是否可以回收。
在 CMS中,其周期性的執(zhí)行一個(gè) concurrent marking phase。 這個(gè)phase中最主要的事情是,識(shí)別哪些老的區(qū)域中充滿了可以回收的對(duì)象,因?yàn)檫@是最有效率和最合適的回收。但在G1中,G1不會(huì)執(zhí)行那個(gè)所謂的 concurrent sweeping phase, 取而代之的是,去識(shí)別那些的最合適的老的區(qū)域是在并發(fā)的“疏散暫?!敝羞M(jìn)行的(后面會(huì)做介紹)。
使用 G1
G1 目前仍然還在試驗(yàn)階段,使用下面兩個(gè)參數(shù)可以打開G1機(jī)制:
-XX:+UnlockExperimentalVMOptions -XX:+UseG1GC
下面是設(shè)置垃圾回收器的暫停時(shí)間:
-XX:MaxGCPauseMillis =50 (設(shè)置暫停時(shí)間為 50ms)
在G1中,你還可以給垃圾回收器的暫停設(shè)置一個(gè)時(shí)間間隔:
-XX:GCPauseIntervalMillis =200 (設(shè)置暫停時(shí)間間隔 200ms)
注意,上面的兩個(gè)參數(shù)只是代表目標(biāo),回收器并不保證。他們可能在某些情況下工作地很好,也可能在其它情況下不行,所以,垃圾回收器并不總是服從這兩個(gè)參數(shù)設(shè)置。
另外,新生代的內(nèi)存大小可以被設(shè)置,這個(gè)參數(shù)同樣會(huì)影響“疏散暫?!钡臅r(shí)間:
-XX:+G1YoungGenSize=512m (設(shè)置新生代內(nèi)存為 512兆字節(jié))
G1 同樣可以使用survivor 空間,是的,這就是多少個(gè)區(qū)域。大小可以由通用的參數(shù)所指定(如: -XX:SurvivorRatio=6).
最后,如果你要發(fā)揮G1的所有潛能,你可以嘗試設(shè)置下面兩個(gè)參數(shù),它們默認(rèn)上是關(guān)閉的,因?yàn)樵谝恍┖芟∮械那闆r下,這兩個(gè)參數(shù)會(huì)發(fā)生race condition(競(jìng)爭(zhēng)條件):
-XX:+G1ParallelRSetUpdatingEnabled
-XX:+G1ParallelRSetScanningEnabled
還有一件事是G1能夠報(bào)告比其它垃圾回收站更詳細(xì)的信息,當(dāng)然,你需要設(shè)置下面這個(gè)參數(shù):
-XX:+PrintGCDetails
這個(gè)參數(shù)會(huì)輸出很多有用的信息供你查看性能與以 trouble-shooting。如果你想要簡(jiǎn)單的日志,你可以把這個(gè)開關(guān)設(shè)置到 -verbosegc 。
狀態(tài)
◆G1 開發(fā)目前主要關(guān)注于解決一些殘留的穩(wěn)定性的問(wèn)題,以及提高性能,并且去除下面的限制:
◆G1 并不完全支持 JVM Tool Interface (JVM TI) 或 Java Management Extensions (JMX),所以,這些監(jiān)控和管理工具無(wú)法正確地作用于G1。
◆G1 不支持增量的永生代collection。如果一個(gè)應(yīng)用在卸載很多的類,因些需要很多的永生代Collection,目前的G1還不支持,不過(guò)最終版會(huì)支持。
關(guān)于垃圾回收器的暫停時(shí)間,G1的表現(xiàn)比起CMS來(lái)說(shuō)是時(shí)好時(shí)壞。所以,還有很多工作需要讓G1的表現(xiàn)更加穩(wěn)定,絕不能比CMS還差,不然G1還有什么意思呢?
【編輯推薦】