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