前言
本節(jié)會(huì)分類介紹下垃圾回收算法, 垃圾回收器的優(yōu)點(diǎn)和缺點(diǎn)
先在腦中有個(gè)大致的框架
本節(jié)自測(cè)問(wèn)題
-
GC 回收算法有哪些 ? 有什么優(yōu)點(diǎn)/缺點(diǎn)
- 提示: 一共 3個(gè)算法 + 一個(gè)思想
-
這些算法對(duì)應(yīng)的回收器實(shí)現(xiàn)有哪些 ?
- 新生代 / 老年代 / all
-
Parallel Scavenge 與 Parallel New 的區(qū)別
- 至少 3點(diǎn) (參見(jiàn): 其他問(wèn)題)
CMS 的4個(gè)階段
-
CMS 的缺點(diǎn)
- 至少 3 點(diǎn)
-
G1GC 的特點(diǎn)
- 至少 3 點(diǎn)
吞吐量?jī)?yōu)先/延遲優(yōu)先下, 分別選用哪個(gè)(些) 垃圾回收器?
-
其他問(wèn)題
- 為什么 Parallel Scanvenge 不能和 CMS 一起用 ?
- Parallel Scanvenge 和 ParNew(Parallel New) 的區(qū)別
- Parallel 和 Concurrent 用在垃圾回收器中分別是什么含義:
GC 算法
回收算法 | 優(yōu)點(diǎn) | 缺點(diǎn) |
---|---|---|
Mark-Sweep 標(biāo)記清除 | 不需要移動(dòng)對(duì)象, 簡(jiǎn)單高效 | 會(huì)產(chǎn)生內(nèi)存碎片 |
Copying 復(fù)制 | 簡(jiǎn)單高效, 沒(méi)有內(nèi)存碎片 | 內(nèi)存使用率低, 可能會(huì)產(chǎn)生內(nèi)存頻繁復(fù)制的情況 |
Mark-Compact 標(biāo)記整理 | 簡(jiǎn)單高效, 沒(méi)有內(nèi)存碎片, 內(nèi)存使用率高 | 仍需要移動(dòng)對(duì)象 |
Generational Collection 分代收集算法(思想) | 分區(qū)回收, 基于大多數(shù)對(duì)象生命周期較短的假設(shè) | 對(duì)長(zhǎng)時(shí)間存活對(duì)象的場(chǎng)景效果不佳 |
垃圾回收器
新生代回收器
回收器名 | 回收算法 | 特點(diǎn) |
---|---|---|
Serial | Copying | 單線程回收器 |
Parallel New | Copying | Parallel New 可以看成 Serial 的多線程版本, 可以和 CMS 一起使用 |
Parallel Scavenge | Copying | 1. Parallel Scavenge 和 Parallel New 類似扼脐,但更加注重吞吐率。2. Parallel Scavenge 不能與 CMS 一起使用软棺。3.Parallel Scavenge 有自適應(yīng)調(diào)節(jié)策略+XX:UseAdaptiveSizePolicy , 調(diào)節(jié)新生代大小, eden/survivor 比例, 晉升老年代年齡等 |
老年代回收器
回收器名 | 回收算法 | 特點(diǎn) |
---|---|---|
Serial Old | Mark-Compact | 單線程 |
Parallel Old | Mark-Compact | 多線程回收 |
CMS - concurrent mark & sweep | Mark-SWEEP | 并發(fā)低延遲,CPU占用高, 在 java9 中被棄用 |
其他回收器
回收器名 | 回收算法 | 特點(diǎn) |
---|---|---|
G1 | Copying & Mark-Compact | 1. 分區(qū), 優(yōu)先回收死亡對(duì)象較多的區(qū)域 2. 不需要其他收集器配合就能獨(dú)立管理整個(gè)堆 3. 高并發(fā), 低延遲, 可預(yù)測(cè)停頓時(shí)間 |
ZGC | Mark-Compact | 1. 可變分區(qū)大小, 低延遲, 通過(guò)LVB 實(shí)現(xiàn)低延遲 |
Parallel Scavenge
Parallel Scavenge收集器提供了兩個(gè)參數(shù)用于精確控制吞吐量砌溺,分別是控制最大垃圾收集停頓時(shí)間的-XX:MaxGCPauseMillis
參數(shù)以及直接設(shè)置吞吐量大小的-XX:GCTimeRatio
參數(shù)影涉。
-
MaxGCPauseMillis
參數(shù)允許的值是一個(gè)大于0的毫秒數(shù),收集器將盡可能地保證內(nèi)存回收花費(fèi)的時(shí)間不超過(guò)設(shè)定值 -
GCTimeRatio
參數(shù)的值應(yīng)當(dāng)是一個(gè)大于0且小于100的整數(shù)
CMS
CMS 的 4個(gè)階段
- 初始標(biāo)記 STW
- 標(biāo)記gc roots直接關(guān)聯(lián)到的對(duì)象
- 并發(fā)標(biāo)記
- gc tracing
- 重新標(biāo)記 STW
- 修正并發(fā)標(biāo)記階段因?yàn)橛脩舫绦蚶^續(xù)運(yùn)行而導(dǎo)致的標(biāo)記變動(dòng)
- 時(shí)長(zhǎng)遠(yuǎn)遠(yuǎn)比并發(fā)標(biāo)記的時(shí)間短
- 并發(fā)清除
- 與用戶線程一起運(yùn)行
CMS 的缺點(diǎn)
- 對(duì)CPU資源敏感, 在cpu不足4個(gè)時(shí), 對(duì)用戶線程影響大
- cms 在并發(fā)清除的過(guò)程中, 仍然有新的垃圾不斷產(chǎn)生 (這部分垃圾被稱為浮動(dòng)垃圾 floating garbage), 所以需要事先預(yù)留一定區(qū)域(相當(dāng)于浪費(fèi)一部分內(nèi)存), 否則如果垃圾回收時(shí), 內(nèi)存不足會(huì)導(dǎo)致 concurrent mode failure, 并使用 serial old 來(lái)回收垃圾了.
- mark-sweep 的算法容易導(dǎo)致內(nèi)存碎片產(chǎn)生
-
-XX:+UseCMSCompactAtFullCollection
在 fullGC的時(shí)候開(kāi)啟內(nèi)存碎片整理, 但這個(gè)過(guò)程無(wú)法并發(fā) -
-XX:CMSFullGCsBeforeCompaction
設(shè)置執(zhí)行多少次不壓縮的 full gc 之后, 進(jìn)行一次 compact
-
選優(yōu)
- 吞吐量?jī)?yōu)先
- Parallel Scavenge + Parallel Old
-XX:+UseParallelOldGC
- Parallel New(ParNew) + CMS (cpu敏感,較低延遲)
-XX:+UseConcMarkSweepGC
- cms 在并發(fā)模式回收失敗的情況下, 會(huì)使用 serial old GC
- Parallel Scavenge + Parallel Old
- 低延遲
- G1GC
-XX:+UseG1GC
- ZGC
- G1GC
下圖來(lái)自于 ①
其他問(wèn)題
為什么 Parallel Scanvenge 不能和 CMS 一起用?
R大回答: https://hllvm-group.iteye.com/group/topic/37095#post-242695
這些XXXGeneration都在HotSpot VM的“分代式GC框架( Generational GC framework )”內(nèi)规伐。本來(lái)HotSpot VM鼓勵(lì)開(kāi)發(fā)者盡量在這個(gè)框架內(nèi)開(kāi)發(fā)GC蟹倾,但后來(lái)有個(gè)開(kāi)發(fā)就是不愿意被這框架憋著,自己硬寫(xiě)了個(gè)沒(méi)有使用已有框架的新并行GC猖闪,并拉攏性能測(cè)試團(tuán)隊(duì)用這個(gè)并行GC來(lái)跑分鲜棠,成績(jī)也還不錯(cuò),于是這個(gè)GC就放進(jìn)HotSpot VM里了培慌。這就是我們現(xiàn)在看到的ParallelScavenge豁陆。
Parallel Scanvenge 和 ParNew(Parallel New) 的區(qū)別
R大回答: https://hllvm-group.iteye.com/group/topic/37095#post-242695
1、PS以前是廣度優(yōu)先順序來(lái)遍歷對(duì)象圖的检柬,JDK6的時(shí)候改為默認(rèn)用深度優(yōu)先順序遍歷献联,并留有一個(gè)UseDepthFirstScavengeOrder參數(shù)來(lái)選擇是用深度還是廣度優(yōu)先。在JDK6u18之后這個(gè)參數(shù)被去掉何址,PS變?yōu)橹挥蒙疃葍?yōu)先遍歷里逆。ParNew則是一直都只用廣度優(yōu)先順序來(lái)遍歷
2、PS完整實(shí)現(xiàn)了adaptive size policy用爪,而ParNew及“分代式GC框架”內(nèi)的其它GC都沒(méi)有實(shí)現(xiàn)完(倒不是不能實(shí)現(xiàn)原押,就是麻煩+沒(méi)人力資源去做)。所以千萬(wàn)千萬(wàn)別在用ParNew+CMS的組合下用UseAdaptiveSizePolicy偎血,請(qǐng)只在使用UseParallelGC或UseParallelOldGC的時(shí)候用它诸衔。
3、由于在“分代式GC框架”內(nèi)颇玷,ParNew可以跟CMS搭配使用笨农,而ParallelScavenge不能。當(dāng)時(shí)ParNew GC被從Exact VM移植到HotSpot VM的最大原因就是為了跟CMS搭配使用帖渠。
4谒亦、在PS成為主要的throughput GC之后,它還實(shí)現(xiàn)了針對(duì)NUMA的優(yōu)化空郊;而ParNew一直沒(méi)有得到NUMA優(yōu)化的實(shí)現(xiàn)份招。
Parallel 和 Concurrent 用在垃圾回收器中分別是什么含義:
Parallel 多條垃圾回收線程同時(shí)工作, 但用戶線程處于等待狀態(tài)
- 如 ParNew Old
Concurrent 指用戶線程與垃圾回收線程同時(shí)執(zhí)行
- 如 CMS
來(lái)自②深入理解 jvm 周志明 3.5.2 ParNew 收集器 P78
參考
-
① Our Collectors - Jon Masamitsu's Weblog
② 深入理解 jvm 周志明
-
③ zgc
與標(biāo)記對(duì)象的傳統(tǒng)算法相比,ZGC在指針上做標(biāo)記狞甚,在訪問(wèn)指針時(shí)加入Load Barrier(讀屏障)锁摔,比如當(dāng)對(duì)象正被GC移動(dòng),指針上的顏色就會(huì)不對(duì)哼审,這個(gè)屏障就會(huì)先把指針更新為有效地址再返回谐腰,也就是孕豹,永遠(yuǎn)只有單個(gè)對(duì)象讀取時(shí)有概率被減速,而不存在為了保持應(yīng)用與GC一致而粗暴整體的Stop The World怔蚌。
轉(zhuǎn)載請(qǐng)注明出處
作者: GiraffeTree - https://giraffetree.me/2019/10/13/java_gc_100_quesions_2/