[Understanding Java Garbage Collection]理解Java垃圾收集(二)

原文鏈接:http://www.cubrid.org/blog/dev-platform/understanding-java-garbage-collection/

GC老年代

老年代GC基本上是在空間慢的時候發生。執行過程與GC的類型有關,因此在你瞭解GC的種類之後更簡單。

根據JDK7,有5中GC類型。

  1. Serial GC
  2. Parallel GC
  3. Parallel Old GC (Parallel Compacting GC)
  4. Concurrnt Mark & Sweep GC (or “CMS”)
  5. Garbage First(G1) GC

以上裏面,serial GC一定不能用在服務器上。GC的類型在桌面計算機還只有一個CPU核的時候被創建。使用serial GC會極大的
減少性能。

下面我們來了解一下每種GC的類型。

Serial GC (-XX:+UseSerialGC)

新生代GC使用這種類型,我們在前面說過。老年代GC使用一種叫做“mark-sweep-compact”的算法。

  1. 算法的第一步是標記老年代中存活的對象。
  2. 然後,它從頭開始檢查堆,只留下存活的對象(清除)。
  3. 最後一步,它從頭開始填滿堆,並把堆分爲兩部分:一部分有對象,一部分沒有對象(壓縮)。

serial GC適合內存比較少和CPU核比較少的情況。

Parallel GC (-XX:+UseParallelGC)

difference-between-the-serial-gc-and-parallel-gc.png
圖4 Serial GC與Parallel GC的區別

從圖上,你可以輕易地看到Serial GC與Parallel GC的區別。serial GC只使用一條線程去執行GC,Parallel GC使用多條線程去處理GC,因此,它更快一點。這種GC在內存足夠和CPU核很多的時候,會比較有用。因此叫做“throughput GC”。

Parallel Old GC(-XX:+UseParallelOldGC)

Parallel Old GC從JDK5更新的時候就開始得到支持。與Parallel GC相比,唯一的區別就是使用的老年代GC算法不一樣。它有幾步:標記-彙總-壓縮。彙總這步與標記-清除-壓縮算法中的清除步驟不一樣的是,它將對象分配到GC預先處理!好的地方。這一步有一點複雜。

CMS GC (-XX:+UseConcMarkSweepGC)

serial-gc-and-cms-gc.png
圖5 Serial GC與CMS GC

你可以從上圖看到,併發標記-清除GC比前面提到的其他GC更復雜一點。最初的初始標記比較簡單。離類加載器最近的存活對象被搜索到。因此暫停時間比較短。在併發標記步驟,存活對象被剛剛跟蹤和確認的對象所引用。這一步的不同是它與其他線程在同一時間執行。在重標記步驟,在併發標記步驟新添加的對象或者停止的對象被檢查。最後,在併發清除步驟,交給垃圾收集器處理。垃圾收集器在其他線程執行的時候啓動。因爲這種GC以這種方式執行,所以暫停時間非常短。CMS GC也叫做低時延GC,用在響應時間很嚴格的程序中

這種GC有短的stop-the-world的時間的優點,也有下面的優點:

  • 與其他GC類型相比,消耗更多的內存和CPU
  • 默認是不支持壓縮步驟的

你在使用這種GC前要仔細考慮。如果因爲內存碎片過多,需要啓動壓縮任務時,stop-the-world時間就會比其他GC要長。你需要檢查多頻繁和多久執行一次壓縮步驟。

G1 GC

最後,我們來學習一下garbage first(G1)GC。

layout-of-g1-gc.png
圖6 G1 GC的佈局

如果你想了解G1 GC,忘記你所知道的所有關於新生代和老年代的東西。你可以從圖中看出,一個對象被分配到一個格子中,然後GC被執行。然後,一旦一個區域滿了,對象就會被分配到其他區域,然後GC就會執行。這裏找不到數據從新生代移動到老年代的步驟。這種GC用來替代有很多問題並飽受爭議的CMS GC。

G1 GC最大的優點是性能。它比我們前面講的其他任何類型的GC都要快。但是在JDK6中,這叫做early access,並且只是用來測試。在JDK7中被正式加進來。我個人看來,在NHN能在實際服務中使用JDK7還需要很長時間(至少一年)。因此你必須等一等。另外,我經常聽說JDK6在應用G1 GC之後,經常崩潰。在穩定之前請等一等。

我會在下面介紹GC優化,但是之前我要告訴你一件事。如果所有創建的對象的大小和類型在程序中是明確的,我們公司中使用的WAS的所有GC選項都會是一樣的。但是WAS創建的所有對象的大小和類型都是依服務而定的,而且設備類型也千差萬別。換句話說,僅僅因爲特定的服務使用GC選項“A”,並不意味着不同的服務使用相同的選項就能獲得最好的結構。有必要通過持續監控和優化找到WAS線程,每個設備的WAS實例和GC選項最合適的參數。這不是我個人的經驗,這來自爲JavaOne 2010創建Oracle JVM的工程師的討論。

這個問題中,我們僅僅看了一下Java中的GC。我們在後面會瞭解更多關於怎麼監控Java GC狀態和優化GC。

我需要提醒一下,我參考了一本2011年11月出版的叫做“Java 性能”的書(亞馬遜,可以通過Safari在線查到,如果有賬號的話),和一本“Java HotSpot虛擬機內存管理”的Oracle官網提供的白皮書。

作者,Sangmin Lee,性能工程實驗室高級工程師,NHN公司。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章