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

1.垃圾如何確認

對于大多數語言中判斷對象是否存活會采用引用計數法:給對象添加一個引用計數器,當有一個地方引用時,計數器就加1,當引用失效時,計數器就減1。任何時刻只要計數器為0則回收。但是這種算法無法解決對象之間互相循環引用的問題。如A引用B,而B又引用A,計數器永遠不為0,這兩個對象再也無任何引用。這樣GC不能回收這兩個對象。
因此,在JAVA中,采用了可達性分析算法來解決這個問題,判斷對象是否存活。
可達性分析算法:通過GCRoots的對象作為起點,從這些節點向下搜索,搜索走過的路徑稱之為引用鏈(Reference Chain),當一個對象到達GCRoots沒有任何鏈相連,則證明此對象不可用,可以被GC回收。

可達性分析算法

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

2.垃圾收集算法

2.1 標記-清除算法

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

2.2復制算法

為了解決效率問題,復制算法應運而生。它將可用內存分為大小相等的兩塊,每次只使用其中一塊,當其中一塊內存耗盡,觸發GC時就將還存在的對象復制到另外一塊內存上面,然后再把已使用過的內存空間一次性清除。這樣實現了對整個半區的GC,內存分配時完全不用考慮碎片的情況。缺點在于這種算法將內存的可用大小縮小了一半。

2.3 標記-整理算法

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

2.4分代收集法

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

3.垃圾收集器

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

HotSpot虛擬機的垃圾收集器

3.1 Serial收集器

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

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

優點:
簡單高效,在單CPU環境中沒有線程開銷,可以獲得最大的效率。
適用于運行在Client模式下的虛擬機。

3.2 ParNew收集器

ParNew收集器是Serial收集器的多線程版本,除了多線程收集之外,其余包括控制參數、收集算法、對象分配規則、回收策略等都與Serial收集器一樣。

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

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

3.3 Parallel Scavenge收集器

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

3.4 Serial Old收集器

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

3.5 Parallel Old收集器

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

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

3.6 CMS 收集器

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

CMS收集器運行示意圖

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

3.7 G1收集器

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

G1收集器運行示意圖

4.垃圾回收器參數總結

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

5. 內存分配與回收策略

MinorGC:新生代發生的垃圾回收動作,一般速度比較快。
MajorGC/FullGC:發生在老年代的GC,出現MajorGC,經常會伴隨一次MinorGC。MajorGC速度一般比MinorGC慢10倍以上。
1.大多數情況下,對象在Eden區中進行分配,當Eden中沒有足夠的分配空間時,虛擬機將進行一次MinorGC。
2.大對象直接進入老年代,避免觸發大量內存復制。
3.長期存活的對象進入老年代。
4.動態對象年齡判定,為了能更好的適應不同的程序的內存狀況,虛擬機并不是永遠需要要求對象的年齡達到MaxTenuringThreshold才能晉升老年代。如果在Survivor空間中相同年齡對象的大小總和大于Surrvivor空間的一半,則年齡大于等于該年齡的對象就可以直接進入老年代。
5.空間分配擔保:在發送MinorGC之前虛擬機會先檢查老年代最大可用的連續內存空間是否大于新生代所有對象的總和,如果條件成了,則MinorGC可以確保安全。如果不成立,則會檢查是否設置了允許擔保失敗,如果允許,則會繼續檢查老年代最大可用連續內存空間是否大于歷次晉升到老年代對象的平均大小,如果大于,將嘗試進行一次MinorGC,如果小于,則要進行一次FullGC。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,156評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,401評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,069評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,873評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,635評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,128評論 1 323
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,203評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,365評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,881評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,733評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,935評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,475評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,172評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,582評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,821評論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,595評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,908評論 2 372

推薦閱讀更多精彩內容