前兩篇文章分別介紹了JVM 運行時內存劃分和堆上的內存分配機制,本文將對垃圾收集器進行介紹,先來看下面這幅圖:

圖中棕色方塊指的是新生代可選的垃圾收集器,藍色方塊指的是老年代垃圾收集器,G1是可以用于新生代和老年代的垃圾收集器。棕色方塊和藍色方塊之間的連線表示連線一端的新生代垃圾收集器和另一端的老年代垃圾收集器可以配置使用作為整個堆的垃圾收集器組合。下面對分代對各個垃圾收集器進行介紹
新生代垃圾收集器
Serial 收集器
- 是最基本、發(fā)展歷史最悠久的收集器
- 是虛擬機在 Client 模式下默認的新生代收集器
- 使用 stop-and-copy(停止-復制)算法,該算法中:
- 新生代被分為三個區(qū)域:Eden區(qū)(簡稱E區(qū)),Survivor0區(qū)(簡稱S0區(qū)),Survivor1區(qū)(簡稱S1區(qū)),默認上,三個區(qū)的空間大小比例為
E區(qū) : S0區(qū) : S1區(qū) = 8 : 1 : 1 - 絕大多數(shù)對象剛創(chuàng)建的時候會被分在 E 區(qū),其中大多數(shù)對象很快消亡(IBM 的統(tǒng)計是98%)
- E 區(qū)是連續(xù)的空間,因此在其上分配空間極快
- 當 E 區(qū)第一次滿的時候,執(zhí)行 Minor GC,將消亡的對象清理掉,并將剩余存活的對象復制到 S0 區(qū)(此時,S1 區(qū)是空閑的)
- 下次 E 區(qū)滿時,再執(zhí)行一次 Minor GC,將 E 區(qū)和 S0 區(qū)消亡的對象清理掉,將存活的對象復制到 S1 區(qū),然后清空 E 區(qū)和 S0 區(qū)
- 當兩個 S 區(qū)切換了幾次后(默認15次),仍然存活的對象,將被復制到老年代
- 新生代被分為三個區(qū)域:Eden區(qū)(簡稱E區(qū)),Survivor0區(qū)(簡稱S0區(qū)),Survivor1區(qū)(簡稱S1區(qū)),默認上,三個區(qū)的空間大小比例為
- 使用單線程來執(zhí)行垃圾收集工作,在進行垃圾收集時,其他工作線程暫停
- 效率較低
ParNew 收集器
- 就是 Serial 的多線程版,除了使用多線程進行垃圾收集之外,其余行為與 Serial 收集器一致
Parallel Scavenge 收集器
- 使用 stop-and-copy(停止-復制)算法
- 使用多線程進行垃圾收集
- 吞吐量優(yōu)先,目標是達到一個可控制的吞吐量
-
吞吐量 = 運行用戶代碼時間 /(運行用戶代碼時間 + 垃圾收集時間),比如,虛擬機總共運行了 100 分鐘,其中垃圾收集花掉一分鐘,那么吞吐量就是 99%
-
- 具有 GC 自適應調節(jié)策略
- 通過 -XX:+UseAdaptiveSizePolicy 開啟
- 當該參數(shù)打開后,就不需要指定新生代大小、Eden 區(qū)與Survivor 區(qū)大小比例、晉升老年代對象年齡等參數(shù)了,虛擬機會根據(jù)當前的運行情況收集性能監(jiān)控信息,動態(tài)調整這些參數(shù)以提供最合適的停頓時間和最大吞吐量
老年代收集器
Serial Old 收集器
- Serial 收集器的老年代版本,同樣是一個單線程收集器,使用 “標記-整理” 算法,該算法分為兩步:
- 標記:遍歷標記出所有存活對象
- 整理:移動所有存活的對象,且按照內存地址次序一次排列,然后將末端內存地址以后的內存全部回收
- 可作為 CMS 收集器的老年代備用方案
Parallel Old 收集器
- 是 Parallel Scavenge 收集器的老年代版本,使用多線程進行垃圾收集并使用 “標記-整理” 算法
CMS 收集器
- 是一種以獲取最短回收停頓時間為目標的收集器
- 使用 “標記-清除” 算法,該算法分為兩步:
- 標記:遍歷以標記出所有存活對象
- 清除:將沒有標記為存活的對象全部清除
- 由于整個過程中耗時最長的多線程標記和清除都與工作線程一起工作,所以,從總體上來說,CMS 收集器的內存回收過程是與工作線程一起執(zhí)行的
- 缺點:
- 會占用更多 CPU 資源:CMS 默認啟動的回收線程數(shù)是
(CPU 數(shù)量 + 3)/4 - 基于 “標記-清理” 算法會產(chǎn)生大量內存碎片,內存碎片過多時,往往容易出現(xiàn)老年代還有很大空間剩余,但是無法找到足夠大的連續(xù)空間來分配大對象,不得不提前觸發(fā)一次 Full GC
- 無法處理在 “標記-清理” 過程的同時產(chǎn)生的垃圾(因為此時工作線程還在運行,在持續(xù)產(chǎn)生垃圾),每次清理都不夠徹底
- 會占用更多 CPU 資源:CMS 默認啟動的回收線程數(shù)是
G1 收集器
- 多線程收集器,收集垃圾的線程和工作線程可同時進行
- 不容易產(chǎn)生內存碎片
- 收集后能提供規(guī)整的可用內存,有利于程序長時間運行
- 可預測的停頓:能讓使用者明確指定一個長度為 M 毫秒的時間片段內,消耗在垃圾收集上的時間不得超過 N 毫秒