這是我公司同事的GC學(xué)習(xí)筆記,寫得蠻詳細(xì)的,由淺入深,循序漸進(jìn),讓人一看就懂,特轉(zhuǎn)到這里。
一、GC特性以及各種GC的選擇
1、垃圾回收器的特性
2、對(duì)垃圾回收器的選擇
2.1 連續(xù) VS. 并行
2.2 并發(fā) VS. stop-the-world
2.3 壓縮 VS. 不壓縮 VS. 復(fù)制
二、GC性能指標(biāo)
三、分代回收
四、J2SE 5.0的HotSpot JVM上的GC學(xué)習(xí) - 分代、GC類型、快速分配
五、J2SE 5.0的HotSpot JVM上的GC學(xué)習(xí) - SerialGC
六、J2SE 5.0的HotSpot JVM上的GC學(xué)習(xí) - ParallelGC
七、J2SE 5.0的HotSpot JVM上的GC學(xué)習(xí) - ParallelCompactingGC
八、J2SE 5.0的HotSpot JVM上的GC學(xué)習(xí) - CMS GC
九、啟動(dòng)參數(shù)學(xué)習(xí)示例
1. GC特性以及各種GC的選擇
1.1 垃圾回收器的特性
該回收的對(duì)象一定要回收,不該回收的對(duì)象一定不能回收
一定要有效,并且要快!盡可能少的暫停應(yīng)用的運(yùn)行
需要在時(shí)間,空間,回收頻率這三個(gè)要素中平衡
內(nèi)存碎片的問(wèn)題(一種解決內(nèi)存碎片的方法,就是壓縮)
可擴(kuò)展性和可伸縮性(內(nèi)存的分配和回收,不應(yīng)該成為跑在多核多線程應(yīng)用上的瓶頸)
對(duì)垃圾回收器的選擇
1.2 連續(xù) VS. 并行
連續(xù)垃圾回收器,即使在多核的應(yīng)用中,在回收時(shí),也只有一個(gè)核被利用。
但并行GC會(huì)使用多核,GC任務(wù)會(huì)被分離成多個(gè)子任務(wù),然后這些子任務(wù)在各個(gè)CPU上并行執(zhí)行。
并行GC的好處是讓GC的時(shí)間減少,但缺點(diǎn)是增加了復(fù)雜度,并且存在產(chǎn)生內(nèi)存碎片的可能。
1.3 并發(fā) VS. stop-the-world
當(dāng)使用stop-the-world 方式的GC在執(zhí)行時(shí),整個(gè)應(yīng)用會(huì)暫停住的。
而并發(fā)是指GC可以和應(yīng)用一起執(zhí)行,不用stop the world。
一般的說(shuō),并發(fā)GC可以做到大部分的運(yùn)行時(shí)間,是可以和應(yīng)用并發(fā)的,但還是有一些小任務(wù),不得不短暫的stop the world。
stop the world 的GC相對(duì)簡(jiǎn)單,因?yàn)?/span>heap被凍結(jié),對(duì)象的活動(dòng)也已經(jīng)停止。但缺點(diǎn)是可能不太滿足對(duì)實(shí)時(shí)性要求很高的應(yīng)用。
相應(yīng)的,并發(fā)GC的stop the world時(shí)間非常短,并且需要做一些額外的事情,因?yàn)椴l(fā)的時(shí)候,對(duì)象的引用狀態(tài)有可能發(fā)生改變的。
所以,并發(fā)GC需要花費(fèi)更多的時(shí)間,并且需要較大的heap。
1.4 壓縮 VS. 不壓縮 VS. 復(fù)制
在GC確定內(nèi)存中哪些是有用的對(duì)象,哪些是可回收的對(duì)象之后,他就可以壓縮內(nèi)存,把擁有的對(duì)象放到一起,并把剩下的內(nèi)存進(jìn)行清理。
在壓縮之后,分配對(duì)象就會(huì)快很多,并且內(nèi)存指針可以很快的指向下一個(gè)要分配的內(nèi)存地址。
一個(gè)不壓縮的GC,就原地把不被引用的對(duì)象回收,他并沒(méi)有對(duì)內(nèi)存進(jìn)行壓縮。好處就是回收的速度變快了;缺點(diǎn)呢,就是產(chǎn)生了碎片。
一般來(lái)說(shuō),在有碎片的內(nèi)存上分配一個(gè)對(duì)象的代價(jià)要遠(yuǎn)遠(yuǎn)大于在沒(méi)有碎片的內(nèi)存上分配。
另外的選擇是使用一個(gè)復(fù)制算法的GC,他是把所有被引用的對(duì)象復(fù)制到另外一個(gè)內(nèi)存區(qū)域中。
使用復(fù)制GC的好處就是,原來(lái)的內(nèi)存區(qū)域,就可以被毫無(wú)顧忌的清空了。但缺點(diǎn)也很明顯,需要更多的內(nèi)存,以及額外的時(shí)間來(lái)復(fù)制。
2. GC性能指標(biāo)
幾個(gè)評(píng)估GC性能的指標(biāo)
吞吐量 應(yīng)用花在非GC上的時(shí)間百分比
GC負(fù)荷 與吞吐量相反,指應(yīng)用花在GC上的時(shí)間百分比
暫停時(shí)間 應(yīng)用花在GC stop-the-world 的時(shí)間
GC頻率 顧名思義
Footprint 一些資源大小的測(cè)量,比如堆的大小
反應(yīng)速度 從一個(gè)對(duì)象變成垃圾道這個(gè)對(duì)象被回收的時(shí)間
一個(gè)交互式的應(yīng)用要求暫停時(shí)間越少越好,然而,一個(gè)非交互性的應(yīng)用,當(dāng)然是希望GC負(fù)荷越低越好。
一個(gè)實(shí)時(shí)系統(tǒng)對(duì)暫停時(shí)間和GC負(fù)荷的要求,都是越低越好。
一個(gè)嵌入式系統(tǒng)當(dāng)然希望Footprint越小越好。
3. 分代回收
3.1 什么是分代
當(dāng)使用分代回收技術(shù),內(nèi)存會(huì)被分為幾個(gè)代(generation)。也就是說(shuō),按照對(duì)象存活的年齡,把對(duì)象放到不同的代中。
使用最廣泛的代,應(yīng)屬年輕代和年老代了。
根據(jù)各種GC算法的特征,可以相應(yīng)的被應(yīng)用到不同的代中。
研究發(fā)現(xiàn):
大部分的對(duì)象在分配后不久,就不被引用了。也就是,他們?cè)诤茉缇蛼炝恕?nbsp;
只有很少的對(duì)象熬過(guò)來(lái)了。
年輕代的GC相當(dāng)?shù)念l繁,高效率并且快。因?yàn)槟贻p代通常比較小,并且很多對(duì)象都是不被引用的。
如果年輕代的對(duì)象熬過(guò)來(lái)了,那么就晉級(jí)到年老代中了。如圖:

通常年老代要比年輕代大,而且增長(zhǎng)也比較慢。所以GC在年老代發(fā)生的頻率非常低,不過(guò)一旦發(fā)生,就會(huì)占據(jù)較長(zhǎng)的時(shí)間。
3.2 總結(jié)
年輕代通常使用時(shí)間占優(yōu)的GC,因?yàn)槟贻p代的GC非常頻繁
年老代通常使用善于處理大空間的GC,因?yàn)槟昀洗目臻g大,GC頻率低
4. J2SE 5.0的HotSpot JVM上的GC學(xué)習(xí) - 分代、GC類型、快速分配
J2SE5.0 update 6 的HotSpot上有4個(gè)GC。
4.1 HotSpot上的分代
分成三部分:年輕代、年老代、永久代
很多的對(duì)象一開(kāi)始是分配在年輕代的,這些對(duì)象在熬過(guò)了一定次數(shù)的young gc之后,就進(jìn)入了年老代。同時(shí),一些比較大的對(duì)象,一開(kāi)始就可能被直接分配到年老代中(因?yàn)槟贻p代比較小嘛)。
4.2 年輕代
年輕代也進(jìn)行劃分,劃分成:一個(gè)Eden和兩個(gè)survivor。如下圖:

大部分的對(duì)象被直接分配到年輕代的eden區(qū)(之前已經(jīng)提到了是,很大的對(duì)象會(huì)被直接分配到年老代中),
survivor區(qū)里面放至少熬過(guò)一個(gè)YGC的對(duì)象,在survivor里面的對(duì)象,才有機(jī)會(huì)被考慮提升到年老代中。
同一時(shí)刻,兩個(gè)survivor只被使用一個(gè),另外一個(gè)是用來(lái)進(jìn)行復(fù)制GC時(shí)使用的。
4.3 GC類型
年輕代的GC叫young GC,有時(shí)候也叫 minor GC。年老代或者永久代的GC,叫 full GC,也叫major GC。
也就是說(shuō),所有的代都會(huì)進(jìn)行GC。
一般的,首先是進(jìn)行年輕代的GC,(使用針對(duì)年輕代的GC),然后是年老代和永久代使用相同的GC。如果要壓縮(解決內(nèi)存碎片問(wèn)題),每個(gè)代需要分別壓縮。
有時(shí)候,如果年老區(qū)本身就已經(jīng)很滿了,滿到無(wú)法放下從survivor熬出來(lái)的對(duì)象,那么,YGC就不會(huì)再次觸發(fā),而是會(huì)使用FullGC對(duì)整個(gè)堆進(jìn)行GC(除了CMS這種GC,因?yàn)?/span>CMS不能對(duì)年輕代進(jìn)行GC)
4.4 快速分配內(nèi)存
多線程進(jìn)行對(duì)象建立的時(shí)候,在為對(duì)象分配內(nèi)存的時(shí)候,就應(yīng)該保證線程安全,為此,就應(yīng)該進(jìn)入全局鎖。但全局鎖是非常消耗性能的。
為此,HotSpot引入了Thread Local Allocation Buffers (TLAB)技術(shù),這種技術(shù)的原理就是為每個(gè)線程分配一個(gè)緩沖,用來(lái)分配線程自己的對(duì)象。
每個(gè)線程只使用自己的TLAB,這樣,就保證了不用使用全局鎖。當(dāng)TLAB不夠用的時(shí)候,才需要使用全局鎖。但這時(shí)候?qū)︽i的時(shí)候,頻率已經(jīng)相當(dāng)?shù)牡土恕?/span>
為了減少TLAB對(duì)空間的消耗,分配器也想了很多方法,平均來(lái)說(shuō),TLAB占用Eden區(qū)的不到1%。
5. J2SE 5.0的HotSpot JVM上的GC學(xué)習(xí) - SerialGC
5.1 串行GC
串行GC,只使用單個(gè)CPU,并且會(huì)stop the world。
5.1.1 young 的串行GC
如下圖:

當(dāng)發(fā)生ygc的時(shí)候,Eden和From的survivor區(qū)會(huì)將被引用的對(duì)象復(fù)制到To這個(gè)survivor種。
如果有些對(duì)象在To survivor放不下,則直接升級(jí)到年老區(qū)。
當(dāng)YGC完成后,內(nèi)存情況如下圖:

5.1.2 old區(qū)的串行GC
年老區(qū)和永久區(qū)使用的是Mark-Sweep-Compact的算法。
mark階段是對(duì)有引用的對(duì)象進(jìn)行標(biāo)識(shí)
sweep是對(duì)垃圾進(jìn)行清理
compact對(duì)把活著的對(duì)象進(jìn)行遷移,解決內(nèi)存碎片的問(wèn)題
如下圖:

5.2 何時(shí)使用串行收集器
串行GC適用于對(duì)暫停時(shí)間要求不嚴(yán),在客戶端下使用。
5.3 串行收集器的選擇
在J2SE5.0上,在非 server 模式下,JVM自動(dòng)選擇串行收集器。
也可以顯示進(jìn)行選擇,在java啟動(dòng)參數(shù)中增加: -XX:+UseSerialGC 。
6. J2SE 5.0的HotSpot JVM上的GC學(xué)習(xí) - ParallelGC
6.1 并行GC
現(xiàn)在已經(jīng)有很多java應(yīng)用跑在多核的機(jī)器上了。
并行的GC,也稱作吞吐量GC,這種GC把多個(gè)CPU都用上了,不讓CPU再空轉(zhuǎn)。
6.2 YGC的并行GC
YGC的情況,還是使用stop-the-world + 復(fù)制算法的GC。
只不過(guò)是不再串行,而是充分利用多個(gè)CPU,減少GC負(fù)荷,增加吞吐量。
如下圖,串行YGC和并行YGC的比較:

6.3 年老區(qū)的并行GC
也是和串行GC一樣,在年老區(qū)和永久區(qū)使用Mark-Sweep-Compact,利用多核增加了吞吐量和減少GC負(fù)荷。
6.4 何時(shí)使用并行GC
對(duì)跑在多核的機(jī)器上,并且對(duì)暫停時(shí)間要求不嚴(yán)格的應(yīng)用。因?yàn)轭l率較低,但是暫停時(shí)間較長(zhǎng)的Full GC還是會(huì)發(fā)生的。
6.5 選擇并行GC
在server模式下,并行GC會(huì)被自動(dòng)選擇。
或者可以顯式選擇并行GC,加啟動(dòng)JVM時(shí)加上參數(shù): -XX:UseParallelGC
7. J2SE 5.0的HotSpot JVM上的GC學(xué)習(xí) - ParallelCompactingGC
7.1 Parallel Compacting GC
parallelCompactingGC是在J2SE5.0 update6 引入的。
parallel compacting GC 與 parallel GC的不同地方,是在年老區(qū)的收集使用了一個(gè)新的算法。并且以后,parallel compacting GC 會(huì)取代 parallem GC的。
7.2 YGC的并行壓縮GC
與并行GC使用的算法一樣:stop-the-world 和 復(fù)制。
7.3 年老區(qū)的并行壓縮GC
他將把年老區(qū)和永久區(qū)從邏輯上劃分成等大的區(qū)域。
分為三個(gè)階段:
標(biāo)記階段,使用多線程對(duì)存在引用的對(duì)象進(jìn)行并行標(biāo)記。
分析階段,GC對(duì)各個(gè)區(qū)域進(jìn)行分析,GC認(rèn)為,在經(jīng)過(guò)上次GC后,越左邊的區(qū)域,有引用的對(duì)象密度要遠(yuǎn)遠(yuǎn)大于右邊的區(qū)域。所以就從左往右分析,當(dāng)某個(gè)區(qū)域的密度達(dá)到一個(gè)值的時(shí)候,就認(rèn)為這是一個(gè)臨界區(qū)域,所以這個(gè)臨界區(qū)域左邊的區(qū)域,將不會(huì)進(jìn)行壓縮,而右邊的區(qū)域,則會(huì)進(jìn)行壓縮。
壓縮階段,多各個(gè)需要壓縮的區(qū)域進(jìn)行并行壓縮。
7.4 什么時(shí)候使用并行壓縮GC
同樣的,適合在多核的機(jī)器上;并且此GC在FGC的時(shí)候,暫停時(shí)間會(huì)更短。
可以使用參數(shù) -XX:ParallelGCThreads=n 來(lái)指定并行的線程數(shù)。
7.5 開(kāi)啟并行壓縮GC
使用參數(shù) -XX:+UseParallelOldGC
8. J2SE 5.0的HotSpot JVM上的GC學(xué)習(xí) - CMS GC
8.1 Concurrent mark sweep GC
很多應(yīng)用對(duì)響應(yīng)時(shí)間的要求要大于吞吐量。
YGC并不暫停多少時(shí)間,但FGC對(duì)時(shí)間的暫用還是很長(zhǎng)的。特別是在年老區(qū)使用的空間較多時(shí)。
因此, HotSpot引入了一個(gè)叫做CMS的收集器,也叫低延時(shí)收集器。
8.2 CMS的YGC
與并行GC同樣的方式: stop-the-world 加上 copy。
8.3 CMS的FGC
CMS的FGC在大部分是和應(yīng)用程序一起并發(fā)的!
CMS在FGC的時(shí)候,一開(kāi)始需要做一個(gè)短暫的暫停,這個(gè)階段稱為最初標(biāo)記:識(shí)別所有被引用的對(duì)象。
在并發(fā)標(biāo)記時(shí)候,會(huì)和應(yīng)用程序一起運(yùn)行。
因?yàn)椴l(fā)標(biāo)記是和程序一起運(yùn)行的,所以在并發(fā)標(biāo)記結(jié)束的時(shí)候,不能保證所有被引用的對(duì)象都被標(biāo)記,
為了解決這個(gè)問(wèn)題,GC又進(jìn)行了一次暫停,這個(gè)階段稱為:重標(biāo)識(shí)(remark)。
在這個(gè)過(guò)程中,GC會(huì)重新對(duì)在并發(fā)標(biāo)階段時(shí)候有修改的對(duì)象做標(biāo)記。
因?yàn)?span style="font-family: "Times New Roman";">remark的暫停要大于最初標(biāo)記,所以在這時(shí)候,需要使用多線程來(lái)并行標(biāo)記。
在上述動(dòng)作完成之后,就可以保證所有被引用的對(duì)象都被標(biāo)記了。
因此,并發(fā)清理階段就可以并發(fā)的收集垃圾了。
下圖是serial gc 和 CMS gc 的對(duì)比:

因?yàn)橐黾雍芏囝~外的動(dòng)作,比如對(duì)被引用的對(duì)象重新標(biāo)記,增加了CMS的工作量,所以他的GC負(fù)荷也相應(yīng)的增加。
CMS是唯一沒(méi)有進(jìn)行壓縮的GC。如下圖:

沒(méi)有壓縮,對(duì)于GC的過(guò)程,是節(jié)約了時(shí)間。但因此產(chǎn)生了內(nèi)存碎片,所以對(duì)于新對(duì)象在年老區(qū)的分配,就產(chǎn)生了速度上的影響,
當(dāng)然,也就包括了對(duì)YGC時(shí)間的影響了。
CMS的另一個(gè)缺點(diǎn),就是他需要的堆比較大,因?yàn)樵诓l(fā)標(biāo)記的時(shí)候和并發(fā)清除的時(shí)候,應(yīng)用程序很有可能在不斷產(chǎn)生新的對(duì)象,而垃圾又還沒(méi)有被刪除。
另外,在最初標(biāo)記之后的并發(fā)標(biāo)記時(shí),原先被引用的對(duì)象,有可能變成垃圾。但在這一次的GC中,這是沒(méi)有被刪除的。這種垃圾叫做:漂流垃圾。
最后,由于沒(méi)有進(jìn)行壓縮,由此而帶來(lái)了內(nèi)存碎片。
為了解決這個(gè)問(wèn)題,CMS對(duì)熱點(diǎn)object大小進(jìn)行了統(tǒng)計(jì),并且估算之后的需求,然后把空閑的內(nèi)存進(jìn)行拆分或者合并來(lái)滿足后續(xù)的需求。
與其他的GC不同,CMS并不在年老區(qū)滿了之后才開(kāi)始GC,他需要提前進(jìn)行GC,用以滿足在GC同時(shí)需要額外的內(nèi)存。
如果在GC的同時(shí),內(nèi)存不能滿足要求了,則GC就變成了并行GC或者串行GC。
為了防止這種情況,會(huì)根據(jù)上一次GC的統(tǒng)計(jì)來(lái)確定啟動(dòng)時(shí)間。
或者是當(dāng)年老區(qū)超過(guò)初始容量的話,CMS GC就會(huì)啟動(dòng)。
初始容量的設(shè)置可以在JVM啟動(dòng)時(shí)增加參數(shù): -XX:CMSInitiatingOccupancyFraction=n
n是一個(gè)百分比,默認(rèn)值為68。
總之,CMS比并行GC花費(fèi)了更少的暫停時(shí)間,但是犧牲了吞吐量,以及需要更大的堆區(qū)。
8.4 額外模式
為了防止在并發(fā)標(biāo)記的時(shí)候,GC線程長(zhǎng)期占用CPU,CMS可以把并發(fā)標(biāo)記的時(shí)候停下來(lái),把cpu讓給應(yīng)用程序。
收集器會(huì)想并發(fā)標(biāo)記分解成很小的時(shí)間串任務(wù),在YGC之間來(lái)執(zhí)行。
這個(gè)功能對(duì)于機(jī)器的CPU個(gè)數(shù)少,但又想降低暫停時(shí)間的應(yīng)用來(lái)說(shuō),非常有用。
8.5 何時(shí)使用CMS
當(dāng)CPU資源較空閑,并且需要很低的暫停時(shí)間時(shí),可以選擇CMS。比如 web servers。
8.6 選擇CMS
選擇CMS GC: 增加參數(shù) -XX:UseConcMarkSweepGC
開(kāi)啟額外模式: 增加參數(shù) -XX:+CMSIncreamentalMode
9. 結(jié)合線上啟動(dòng)參數(shù)學(xué)習(xí)
線上的啟動(dòng)參數(shù)
-Dprogram.name=run.sh -Xmx2g -Xms2g -Xmn256m -XX:PermSize=128m -Xss256k -XX:+DisableExplicitGC -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:LargePageSizeInBytes=128m -XX:+UseFastAccessorMethods -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70 -Djava.awt.headless=true -Djava.net.preferIPv4Stack=true -Dcom.sun.management.config.file=/home/admin/web-deploy/conf/jmx/jmx_monitor_management.properties -Djboss.server.home.dir=/home/admin/web-deploy/jboss_server -Djboss.server.home.url=file\:/home/admin/web-deploy/jboss_server -Dapplication.codeset=GBK -Ddatabase.codeset=ISO-8859-1 -Ddatabase.logging=false -Djava.endorsed.dirs=/usr/alibaba/jboss/lib/endorsed
其中:
-Xmx2g -Xms2g 表示堆為2G
-Xmn256m 表示新生代為 256m
-Xss256k 設(shè)置每個(gè)線程的堆棧大小。JDK5.0以后每個(gè)線程堆棧大小為1M,以前每個(gè)線程堆棧大小為256K。更具應(yīng)用的線程所需內(nèi)存大小進(jìn)行調(diào)整。在相同物理內(nèi)存下,減小這個(gè)值能生成更多的線程。但是操作系統(tǒng)對(duì)一個(gè)進(jìn)程內(nèi)的線程數(shù)還是有限制的,不能無(wú)限生成,經(jīng)驗(yàn)值在3000~5000左右
-XX:PermSize=128m 表示永久區(qū)為128m
-XX:+DisableExplicitGC 禁用顯示的gc,程序程序中使用System.gc()中進(jìn)行垃圾回收,使用這個(gè)參數(shù)后系統(tǒng)自動(dòng)將 System.gc() 調(diào)用轉(zhuǎn)換成一個(gè)空操作
-XX:+UseConcMarkSweepGC 表示使用CMS
-XX:+CMSParallelRemarkEnabled 表示并行remark
-XX:+UseCMSCompactAtFullCollection 表示在FGC之后進(jìn)行壓縮,因?yàn)?/span>CMS默認(rèn)不壓縮空間的。
-XX:+UseCMSInitiatingOccupancyOnly 表示只在到達(dá)閥值的時(shí)候,才進(jìn)行CMS GC
-XX:CMSInitiatingOccupancyFraction=70 設(shè)置閥值為70%,默認(rèn)為68%。
-XX:+UseCompressedOops JVM優(yōu)化之壓縮普通對(duì)象指針(CompressedOops),通常64位JVM消耗的內(nèi)存會(huì)比32位的大1.5倍,這是因?yàn)閷?duì)象指針在64位架構(gòu)下,長(zhǎng)度會(huì)翻倍(更寬的尋址)。對(duì)于那些將要從32位平臺(tái)移植到64位的應(yīng)用來(lái)說(shuō),平白無(wú)辜多了1/2的內(nèi)存占用,這是開(kāi)發(fā)者不愿意看到的。幸運(yùn)的是,從JDK 1.6 update14開(kāi)始,64 bit JVM正式支持了 -XX:+UseCompressedOops 這個(gè)可以壓縮指針,起到節(jié)約內(nèi)存占用的新參數(shù).
關(guān)于-XX:+UseCMSInitiatingOccupancyOnly 和 -XX:CMSInitiatingOccupancyFraction ,詳細(xì)解釋見(jiàn)下:
The concurrent collection generally cannot be sped up but it can be started earlier.
A concurrent collection starts running when the percentage of allocated space in the old generation crosses a threshold. This threshold is calculated based on general experience with the concurrent collector. If full collections are occurring, the concurrent collections may need to be started earlier. The command line flag CMSInitiatingOccupancyFraction can be used to set the level at which the collection is started. Its default value is approximately 68%. The command line to adjust the value is
-XX:CMSInitiatingOccupancyFraction=<percent>
The concurrent collector also keeps statistics on the promotion rate into the old generation for the application and makes a prediction on when to start a concurrent collection based on that promotion rate and the available free space in the old generation. Whereas the use of CMSInitiatingOccupancyFraction must be conservative to avoid full collections over the life of the application, the start of a concurrent collection based on the anticipated promotion adapts to the changing requirements of the application. The statistics that are used to calculate the promotion rate are based on the recent concurrent collections. The promotion rate is not calculated until at least one concurrent collection has completed so at least the first concurrent collection has to be initiated because the occupancy has reached CMSInitiatingOccupancyFraction . Setting CMSInitiatingOccupancyFraction to 100 would not cause only the anticipated promotion to be used to start a concurrent collection but would rather cause only non-concurrent collections to occur since a concurrent collection would not start until it was already too late. To eliminate the use of the anticipated promotions to start a concurrent collection set UseCMSInitiatingOccupancyOnly to true.
-XX:+UseCMSInitiatingOccupancyOnly
關(guān)于內(nèi)存管理完整詳細(xì)信息,請(qǐng)查看這份文檔:http://www.oracle.com/technetwork/java/javase/memorymanagement-whitepaper-150215.pdf