參考官網html
使用G1收集器時,java堆的內存會劃分爲多個大小相等的獨立區域(Region),他也有新生代和老年代的概念,可是新生代和老年代再也不是物理隔離的,它們都是一部分Region(不須要連續)的集合,以下圖所示:粉色的表明新生代,沒有字母的是eden,有s的是survivor ,老年代是淺藍的O,還有一個H是humongous,也是老年代,咱們在jvm - 堆內存分配提過,大對象直接進入老年代,這個humongous就是存儲大對象的,也就是說若是對象內存大小大於Region的一半大小,那就會給一個專門的Region存放,若是對象大於一個Region的大小,那就用多個Region存放。
咱們只畫了16個Region,並非說堆只分配了16個,在沒有用-XX:G1HeapRegionSize去指定的狀況下,默認是2048個,Region的個數必須是2的倍數,每一個Region的大小在1到32M之間。
新生代的大小在5%到60%之間,能夠經過-XX:G1NewSizePercent=5
,-XX:G1MaxNewSizePercent=60
來設置。java
G1的另一個特色,就是創建可預測的停頓時間模型。G1跟蹤各個Region的回收價值,並在後臺維護一個優先列表,每次根據容許的收集時間,優先回收價值最大的Region,保證了在有限的時間內獲取儘量高的收集效率,停頓時間默認200ms,用-XX:MaxGCPauseMillis
設置。
好比下圖,第一個新生代的Region回收10M須要5ms,第二個新生代的Region回收20M也只要5ms,第三個新生代的Region回收10M卻須要10ms,若是指定他須要5ms內回收20M的垃圾,他會直接去回收第二個新生代的Region,而不是回收第一個和第三個新生代的Region。算法
上面提過,新生代的內存空間最多佔用60%,當60%的空間用完的時候,就會觸發新生代的回收。新生代的回收是用複製算法的,與以前不一樣的是,他會考慮到停頓時間。segmentfault
老年代回收分爲:初始標記、併發標記、最終標記、混合回收。
前面三個階段跟jvm - CMS收集器的前面三個相似。
混合回收,是說他並不會僅僅回收老年代的垃圾,也會回收新生代的垃圾,他會根據停頓時間,儘量的多回收Region。因爲在停頓時間內回收的垃圾可能不會不少,因此這個階段會進行屢次的混合回收,默認是8次,能夠經過-XX:G1MixedGCCountTarget
設置。
若是混合回收的時候,發現Region僅佔有5%了,那他就會中止回收,不會一直回收8次。
混合回收的基於複製算法的,因此大對象的複製會比較耗時,若是某個老年代的Region超過85%的對象是存活的,那他不會被回收,經過-XX:G1MixedGCLiveThresholdPercent
設置。併發