深入理解java虛擬機學習筆記(二) jvm垃圾收集器和內存分配策略

1.垃圾如何確認

對于大多數(shù)語言中判斷對象是否存活會采用引用計數(shù)法:給對象添加一個引用計數(shù)器,當有一個地方引用時痒留,計數(shù)器就加1,當引用失效時蠢沿,計數(shù)器就減1伸头。任何時刻只要計數(shù)器為0則回收。但是這種算法無法解決對象之間互相循環(huán)引用的問題舷蟀。如A引用B,而B又引用A恤磷,計數(shù)器永遠不為0,這兩個對象再也無任何引用野宜。這樣GC不能回收這兩個對象扫步。
因此,在JAVA中匈子,采用了可達性分析算法來解決這個問題河胎,判斷對象是否存活。
可達性分析算法:通過GCRoots的對象作為起點虎敦,從這些節(jié)點向下搜索游岳,搜索走過的路徑稱之為引用鏈(Reference Chain),當一個對象到達GCRoots沒有任何鏈相連其徙,則證明此對象不可用胚迫,可以被GC回收。

可達性分析算法

上圖藍色部分將會被GC回收擂橘。

2.垃圾收集算法

2.1 標記-清除算法

標記-清除算法是最基礎的垃圾收集算法晌区。分為標記和清除兩個階段:
首先標記出需要回收的對象,在標記完成后統(tǒng)一回收所有被標記的對象。
存在的問題: 一是效率低朗若,標記和清除兩個過程效率都不高恼五。二是空間問題,標記清除后會產生大量的不連續(xù)的內存碎片哭懈≡致空間碎片太多會導致程序在運行過程中需要分配較大對象時無法找到連續(xù)內存而不得不提前觸發(fā)GC。

2.2復制算法

為了解決效率問題遣总,復制算法應運而生睬罗。它將可用內存分為大小相等的兩塊,每次只使用其中一塊旭斥,當其中一塊內存耗盡容达,觸發(fā)GC時就將還存在的對象復制到另外一塊內存上面,然后再把已使用過的內存空間一次性清除垂券。這樣實現(xiàn)了對整個半區(qū)的GC花盐,內存分配時完全不用考慮碎片的情況。缺點在于這種算法將內存的可用大小縮小了一半菇爪。

2.3 標記-整理算法

復制算法當對象存活率較高的情況時算芯,照樣會出現(xiàn)效率低下的問題,另外內存要浪費50%凳宙。為了避免上述問題熙揍,出現(xiàn)了 標記-整理算法。(mark-compact) 其標記過程與標記-清除算法一樣氏涩,但后續(xù)步驟不直接清除届囚,而是讓所有存活的對象都向一端移動,然后直接清理掉邊界以外的內存削葱。

2.4分代收集法

根據對象的存活周期將內存分為幾塊奖亚,如當前hotsport就分為新生代和老年代淳梦,然后在各個年代采用不同的收集算法析砸。新生代采用復制算法,老年代采用標記清除或者標記整理算法爆袍。

3.垃圾收集器

垃圾收集器是內存回收算法的具體實現(xiàn)首繁。不同的廠商不同版本的虛擬機對垃圾收集器的實現(xiàn)有很大差別。在HotSport虛擬機1.7版本中陨囊,所有垃圾收集器如下圖所示:

HotSpot虛擬機的垃圾收集器

3.1 Serial收集器

Serial收集器是一個單線程收集器弦疮,只會使用一條線程去收集,同時需要暫停其他所有工作線程蜘醋,直至收集結束。

Serial/Serial Old 收集器運行示意圖

優(yōu)點:
簡單高效,在單CPU環(huán)境中沒有線程開銷熙侍,可以獲得最大的效率。
適用于運行在Client模式下的虛擬機编检。

3.2 ParNew收集器

ParNew收集器是Serial收集器的多線程版本,除了多線程收集之外扰才,其余包括控制參數(shù)允懂、收集算法、對象分配規(guī)則衩匣、回收策略等都與Serial收集器一樣蕾总。

ParNew/Serial Old收集器運行示意圖

ParNew收集器是jvmServer模式下的首選新生代收集器,除Serial收集器外琅捏,只有ParNew收集器能與CMS收集器配合工作生百。默認開啟的收集線程數(shù)與CPU的數(shù)量相同”樱可以通過 -XX:parallelGCThreads參數(shù)來限制垃圾收集的線程數(shù)置侍。

3.3 Parallel Scavenge收集器

Parallel Scavenge收集器是一個新生代收集器,也采用復制算法拦焚,并行多線程收集蜡坊。特點在于達到一個可控目標吞吐量(Throughput)。
吞吐量 = 運行用戶代碼的時間/(運行用戶代碼的時間+GC耗時)赎败。
-XX:MaxGCPauseMillis 設置停頓時間秕衙。
-XX:GCTimeratio 設置吞吐量。
Parallel Scavenge收集器 能夠根據上述兩個參數(shù)進行自適應調節(jié)僵刮。

3.4 Serial Old收集器

Serial Old收集器是Serial收集器的老年代版本据忘,同樣式一個單線程收集器,使用標記整理算法搞糕。收集器的主要意義也是提供給Client模式下使用勇吊,在Server模式下,主要有兩大用途:

3.5 Parallel Old收集器

Parallel Old收集器是Parallel Scavenge收集器的老年代版本窍仰,使用多線程的標記整理算法汉规。
在注重吞吐量以及CPU資源敏感的場合,優(yōu)先考慮Parallel Scavenge和Parallel Old的組合進行收集驹吮。

parallel Scavenge/Parallel Old收集器運行示意圖

3.6 CMS 收集器

CMS(Concurrent Mark Sweep)收集器是一種以獲得最短回收停頓時間為目標的收集器针史。主要應用在互聯(lián)網或BS系統(tǒng)的服務器上,這類應用尤其重視服務器的響應速度碟狞,希望停頓時間最短啄枕,以給用戶最好的體驗。
CMS時基于標記清除算法實現(xiàn)的族沃,主要分為4個步驟:
初始標記(CMS initial mark):標記GC Roots能直接關聯(lián)到的對象频祝,速度很快泌参。
并發(fā)標記(CMS concurrent mark):進行roots tracing過程。
重新標記(CMS remark):修正并發(fā)標記階段因用戶程序繼續(xù)運作而導致標記產生變動的哪一部分對象的標記記錄常空,這個極端停頓時間比初始標記長及舍。但遠比并發(fā)標記短。
并發(fā)清除(CMS concurrent sweep):回收資源窟绷。
上述步驟中锯玛,初始標記、重新標記這兩個步驟需要停止所有線程兼蜈。

CMS收集器運行示意圖

CMS收集器缺點:
CMS收集器對CPU資源非常敏感攘残,在CPU資源很匱乏時,效率會非常滴为狸,造成停頓時間過長歼郭。
CMS收集器無法處理浮動垃圾,即在CMS收集器收集過程中新產生的垃圾辐棒,如果浮動垃圾較大病曾,會導致CMS失敗。當CMS失敗后漾根,會啟動后背預案泰涂,臨時啟用SerialOld收集器來進行老年代收集。這樣停頓時間就會比較長辐怕。
CMS收集器基于標記清除算法逼蒙,會產生大量的內存碎片,需要額外開啟內存整理寄疏。通過參數(shù) -XX:CMSFullGCsBeforeCompation是牢,設置執(zhí)行多少次不壓縮的GC后進行一次壓縮。

3.7 G1收集器

G1是一款面向服務端的垃圾收集器陕截,具有如下特點:
并行與并發(fā):G1能充分利用多CPU驳棱,多環(huán)境下的硬件優(yōu)勢,使用多個CPU來縮短停頓時間农曲,部分其他收集器需要停頓的動作社搅,G1中可以并發(fā)的方式進行執(zhí)行。
分代收集:G1中仍然使用分代收集朋蔫。
空間整合:G1基于標記整理算法實現(xiàn)收集罚渐,局部來看是基于復制算法却汉,運行期間不會產生內存碎片驯妄。
可預測停頓:可以指定停頓的時間片段。
G1可分為如下步驟:
初始標記(Initial marking)
并發(fā)標記(Concurrent marking)
最終標記(Final Marking)
篩選回收(Live Data Counting and evacuation)

G1收集器運行示意圖

4.垃圾回收器參數(shù)總結

參數(shù) 描述
UserSerialGC 虛擬機在client模式下的默認值合砂,打開此開關后青扔,用于Serial+Serial Old的收集器組合進行內存回收
UserParNewGC 打開此開關 使用ParNew + Serial Old收集器組合進行內存回收
UseConcMarkSweepGC 打開此開關源织,使用ParNew+CMS+Serial Old收集器組合進行內存回收。Serial Old在CMS收集器出現(xiàn)concurrent Mode Failure 失敗后的后備收集器
UseParallelGC 在server模式下的默認值微猖,打開此開關后使用Scavenge+Serial Old收集器組合進行回收
UseParallelOldGC 打開此開關后使用 Parallel Scavenge+Parallel Old收集器組合進行內存回收
SurvivorRatio 新生代中Eden區(qū)域與Survivor區(qū)域的比值谈息,默認為8,表示Eden:Survivor=8:1
PretenureSizeThreshold 直接晉升到老年代對象的大小凛剥,設置這個參數(shù)后大于這個參數(shù)的對象直接在老年代中分配
MaxTenuringThreshold 晉升老年代對象的年齡,每個對象堅持一次MnorGC年齡就加一侠仇,當超過這個參數(shù)值就進入老年代
UseAdaptiveSizePolicy 動態(tài)調整java堆各個區(qū)域的大小以及進入老年代的年齡
HandlePromotionFailure 是否允許分配擔保失敗,即老年代剩余空間不足以應付新生代整個對象都存活的特殊情況
ParalleGCThreads 設置并行GC時進行內存回收的線程數(shù)
GCTimeratio GC時間占總時間比率犁珠,默認值為99逻炊,允許1%的GC時間。只在Parallel Seavenge收集器時生效
MaxGCPauseMillis 設置GC的最大停頓時間犁享,只在Parallel Seavenge收集器時生效
CMSInitiatingOccupancyFration 設置CMS老年代空間被使用多少后觸發(fā)GC余素,默認值為68%,只在CMS收集器時生效
UseCMSCompactAtFullCollection 設置CMS收集器完成垃圾收集后是否需要進行一次碎片整理炊昆,只在CMS垃圾收集器時生效
CMSFullGCBeforeCompaction 設置CMS收集器進行若干次垃圾收集后再啟動一次內存碎片整理桨吊,只在CMS垃圾收集器時生效

5. 內存分配與回收策略

MinorGC:新生代發(fā)生的垃圾回收動作,一般速度比較快凤巨。
MajorGC/FullGC:發(fā)生在老年代的GC视乐,出現(xiàn)MajorGC,經常會伴隨一次MinorGC敢茁。MajorGC速度一般比MinorGC慢10倍以上炊林。
1.大多數(shù)情況下,對象在Eden區(qū)中進行分配卷要,當Eden中沒有足夠的分配空間時渣聚,虛擬機將進行一次MinorGC。
2.大對象直接進入老年代僧叉,避免觸發(fā)大量內存復制奕枝。
3.長期存活的對象進入老年代。
4.動態(tài)對象年齡判定瓶堕,為了能更好的適應不同的程序的內存狀況隘道,虛擬機并不是永遠需要要求對象的年齡達到MaxTenuringThreshold才能晉升老年代。如果在Survivor空間中相同年齡對象的大小總和大于Surrvivor空間的一半郎笆,則年齡大于等于該年齡的對象就可以直接進入老年代谭梗。
5.空間分配擔保:在發(fā)送MinorGC之前虛擬機會先檢查老年代最大可用的連續(xù)內存空間是否大于新生代所有對象的總和,如果條件成了宛蚓,則MinorGC可以確保安全激捏。如果不成立,則會檢查是否設置了允許擔保失敗凄吏,如果允許远舅,則會繼續(xù)檢查老年代最大可用連續(xù)內存空間是否大于歷次晉升到老年代對象的平均大小闰蛔,如果大于,將嘗試進行一次MinorGC图柏,如果小于序六,則要進行一次FullGC。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末蚤吹,一起剝皮案震驚了整個濱河市例诀,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌裁着,老刑警劉巖余佃,帶你破解...
    沈念sama閱讀 222,104評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異跨算,居然都是意外死亡爆土,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評論 3 399
  • 文/潘曉璐 我一進店門诸蚕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來步势,“玉大人,你說我怎么就攤上這事背犯』荡瘢” “怎么了?”我有些...
    開封第一講書人閱讀 168,697評論 0 360
  • 文/不壞的土叔 我叫張陵漠魏,是天一觀的道長倔矾。 經常有香客問我,道長柱锹,這世上最難降的妖魔是什么哪自? 我笑而不...
    開封第一講書人閱讀 59,836評論 1 298
  • 正文 為了忘掉前任,我火速辦了婚禮禁熏,結果婚禮上壤巷,老公的妹妹穿的比我還像新娘。我一直安慰自己瞧毙,他們只是感情好胧华,可當我...
    茶點故事閱讀 68,851評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著宙彪,像睡著了一般矩动。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上释漆,一...
    開封第一講書人閱讀 52,441評論 1 310
  • 那天悲没,我揣著相機與錄音,去河邊找鬼灵汪。 笑死檀训,一個胖子當著我的面吹牛柑潦,可吹牛的內容都是我干的享言。 我是一名探鬼主播峻凫,決...
    沈念sama閱讀 40,992評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼览露!你這毒婦竟也來了荧琼?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,899評論 0 276
  • 序言:老撾萬榮一對情侶失蹤差牛,失蹤者是張志新(化名)和其女友劉穎命锄,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體偏化,經...
    沈念sama閱讀 46,457評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡脐恩,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,529評論 3 341
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了侦讨。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片驶冒。...
    茶點故事閱讀 40,664評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖韵卤,靈堂內的尸體忽然破棺而出骗污,到底是詐尸還是另有隱情,我是刑警寧澤沈条,帶...
    沈念sama閱讀 36,346評論 5 350
  • 正文 年R本政府宣布需忿,位于F島的核電站,受9級特大地震影響蜡歹,放射性物質發(fā)生泄漏屋厘。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,025評論 3 334
  • 文/蒙蒙 一月而、第九天 我趴在偏房一處隱蔽的房頂上張望擅这。 院中可真熱鬧,春花似錦景鼠、人聲如沸仲翎。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽溯香。三九已至,卻和暖如春浓恶,著一層夾襖步出監(jiān)牢的瞬間玫坛,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評論 1 272
  • 我被黑心中介騙來泰國打工包晰, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留湿镀,地道東北人炕吸。 一個月前我還...
    沈念sama閱讀 49,081評論 3 377
  • 正文 我出身青樓,卻偏偏與公主長得像勉痴,于是被迫代替她去往敵國和親赫模。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,675評論 2 359

推薦閱讀更多精彩內容