占小狼 轉(zhuǎn)載請(qǐng)注明原創(chuàng)出處躺孝,謝謝祖搓!
為解決CMS算法產(chǎn)生空間碎片和其它一系列的問題缺陷,HotSpot提供了另外一種垃圾回收策略筋量,G1(Garbage First)算法烹吵,通過參數(shù)-XX:+UseG1GC
來啟用,該算法在JDK 7u4版本被正式推出桨武,官網(wǎng)對(duì)此描述如下:
The Garbage-First (G1) collector is a server-style garbage collector, targeted for multi-processor machines with large memories. It meets garbage collection (GC) pause time goals with a high probability, while achieving high throughput. The G1 garbage collector is fully supported in Oracle JDK 7 update 4 and later releases. The G1 collector is designed for applications that:
- Can operate concurrently with applications threads like the CMS collector.
- Compact free space without lengthy GC induced pause times.
- Need more predictable GC pause durations.
- Do not want to sacrifice a lot of throughput performance.
- Do not require a much larger Java heap.
G1垃圾收集算法主要應(yīng)用在多CPU大內(nèi)存的服務(wù)中肋拔,在滿足高吞吐量的同時(shí),竟可能的滿足垃圾回收時(shí)的暫停時(shí)間呀酸,該設(shè)計(jì)主要針對(duì)如下應(yīng)用場(chǎng)景:
- 垃圾收集線程和應(yīng)用線程并發(fā)執(zhí)行凉蜂,和CMS一樣
- 空閑內(nèi)存壓縮時(shí)避免冗長(zhǎng)的暫停時(shí)間
- 應(yīng)用需要更多可預(yù)測(cè)的GC暫停時(shí)間
- 不希望犧牲太多的吞吐性能
- 不需要很大的Java堆 (翻譯的有點(diǎn)虛,多大才算大七咧?)
堆內(nèi)存結(jié)構(gòu)
1跃惫、以往的垃圾回收算法,如CMS艾栋,使用的堆內(nèi)存結(jié)構(gòu)如下:
- 新生代:eden space + 2個(gè)survivor
- 老年代:old space
- 持久代:1.8之前的perm space
- 元空間:1.8之后的metaspace
這些space必須是地址連續(xù)的空間爆存。
2、在G1算法中蝗砾,采用了另外一種完全不同的方式組織堆內(nèi)存先较,堆內(nèi)存被劃分為多個(gè)大小相等的內(nèi)存塊(Region),每個(gè)Region是邏輯連續(xù)的一段內(nèi)存悼粮,結(jié)構(gòu)如下:
每個(gè)Region被標(biāo)記了E闲勺、S、O和H扣猫,說明每個(gè)Region在運(yùn)行時(shí)都充當(dāng)了一種角色菜循,其中H是以往算法中沒有的,它代表Humongous申尤,這表示這些Region存儲(chǔ)的是巨型對(duì)象(humongous object癌幕,H-obj),當(dāng)新建對(duì)象大小超過Region大小一半時(shí)昧穿,直接在新的一個(gè)或多個(gè)連續(xù)Region中分配勺远,并標(biāo)記為H。
Region
堆內(nèi)存中一個(gè)Region的大小可以通過-XX:G1HeapRegionSize
參數(shù)指定时鸵,大小區(qū)間只能是1M胶逢、2M、4M、8M初坠、16M和32M和簸,總之是2的冪次方,如果G1HeapRegionSize為默認(rèn)值碟刺,則在堆初始化時(shí)計(jì)算Region的實(shí)踐大小比搭,具體實(shí)現(xiàn)如下:
默認(rèn)把堆內(nèi)存按照2048份均分,最后得到一個(gè)合理的大小南誊。
GC模式
G1中提供了三種模式垃圾回收模式身诺,young gc、mixed gc 和 full gc抄囚,在不同的條件下被觸發(fā)霉赡。
young gc
發(fā)生在年輕代的GC算法,一般對(duì)象(除了巨型對(duì)象)都是在eden region中分配內(nèi)存幔托,當(dāng)所有eden region被耗盡無法申請(qǐng)內(nèi)存時(shí)穴亏,就會(huì)觸發(fā)一次young gc,這種觸發(fā)機(jī)制和之前的young gc差不多重挑,執(zhí)行完一次young gc嗓化,活躍對(duì)象會(huì)被拷貝到survivor region或者晉升到old region中,空閑的region會(huì)被放入空閑列表中谬哀,等待下次被使用刺覆。
參數(shù) | 含義 |
---|---|
-XX:MaxGCPauseMillis | 設(shè)置G1收集過程目標(biāo)時(shí)間,默認(rèn)值200ms |
-XX:G1NewSizePercent | 新生代最小值史煎,默認(rèn)值5% |
-XX:G1MaxNewSizePercent | 新生代最大值谦屑,默認(rèn)值60% |
mixed gc
當(dāng)越來越多的對(duì)象晉升到老年代old region時(shí),為了避免堆內(nèi)存被耗盡篇梭,虛擬機(jī)會(huì)觸發(fā)一個(gè)混合的垃圾收集器氢橙,即mixed gc,該算法并不是一個(gè)old gc恬偷,除了回收整個(gè)young region悍手,還會(huì)回收一部分的old region,這里需要注意:是一部分老年代袍患,而不是全部老年代坦康,可以選擇哪些old region進(jìn)行收集,從而可以對(duì)垃圾回收的耗時(shí)時(shí)間進(jìn)行控制协怒。
那么mixed gc什么時(shí)候被觸發(fā)涝焙?
先回顧一下cms的觸發(fā)機(jī)制卑笨,如果添加了以下參數(shù):
-XX:CMSInitiatingOccupancyFraction=80
-XX:+UseCMSInitiatingOccupancyOnly
當(dāng)老年代的使用率達(dá)到80%時(shí)孕暇,就會(huì)觸發(fā)一次cms gc。相對(duì)的,mixed gc中也有一個(gè)閾值參數(shù) -XX:InitiatingHeapOccupancyPercent
妖滔,當(dāng)老年代大小占整個(gè)堆大小百分比達(dá)到該閾值時(shí)隧哮,會(huì)觸發(fā)一次mixed gc.
mixed gc的執(zhí)行過程有點(diǎn)類似cms,主要分為以下幾個(gè)步驟:
- initial mark: 初始標(biāo)記過程座舍,整個(gè)過程STW沮翔,標(biāo)記了從GC Root可達(dá)的對(duì)象
- concurrent marking: 并發(fā)標(biāo)記過程,整個(gè)過程gc collector線程與應(yīng)用線程可以并行執(zhí)行曲秉,標(biāo)記出GC Root可達(dá)對(duì)象衍生出去的存活對(duì)象采蚀,并收集各個(gè)Region的存活對(duì)象信息
- remark: 最終標(biāo)記過程,整個(gè)過程STW承二,標(biāo)記出那些在并發(fā)標(biāo)記過程中遺漏的榆鼠,或者內(nèi)部引用發(fā)生變化的對(duì)象
- clean up: 垃圾清除過程,如果發(fā)現(xiàn)一個(gè)Region中沒有存活對(duì)象亥鸠,則把該Region加入到空閑列表中
full gc
如果對(duì)象內(nèi)存分配速度過快妆够,mixed gc來不及回收,導(dǎo)致老年代被填滿负蚊,就會(huì)觸發(fā)一次full gc神妹,G1的full gc算法就是單線程執(zhí)行的serial old gc,會(huì)導(dǎo)致異常長(zhǎng)時(shí)間的暫停時(shí)間家妆,需要進(jìn)行不斷的調(diào)優(yōu)鸵荠,盡可能的避免full gc.