JVM的垃圾回收機(jī)制指的是對(duì)堆中的垃圾對(duì)象進(jìn)行回收猜憎。那么我將從三個(gè)方面來進(jìn)行學(xué)習(xí)和整理届搁,即:
- 對(duì)象被判定為垃圾的標(biāo)準(zhǔn);
- 垃圾回收算法潜腻;
- 年輕代和老年代中常見的垃圾收集器
對(duì)象被判定為垃圾的標(biāo)準(zhǔn)
引用計(jì)數(shù)法
- 通過判斷對(duì)象的引用數(shù)量來決定對(duì)象是否可以被回收
- 為每個(gè)對(duì)象設(shè)置一個(gè)引用計(jì)數(shù)器埃儿,被引用則計(jì)數(shù)+1,引用失效則計(jì)數(shù)-1
- 引用計(jì)數(shù)為0時(shí)對(duì)象實(shí)例可以看作垃圾
- 優(yōu)點(diǎn):簡(jiǎn)單高效融涣;缺點(diǎn):無(wú)法檢測(cè)循環(huán)引用童番,導(dǎo)致內(nèi)存泄漏
可達(dá)性算法
- 通過判斷對(duì)象的引用鏈?zhǔn)欠窨蛇_(dá)來決定對(duì)象是否可以被回收
- 起點(diǎn):GC Roots
- 可以作為GC Root的對(duì)象:1. 虛擬機(jī)棧中引用的對(duì)象;2.方法區(qū)中的常量引用的對(duì)象威鹿;3.方法區(qū)中的類靜態(tài)屬性引用的對(duì)象剃斧;4.本地方法棧中JNI(native方法)的引用對(duì)象;5.活躍線程的引用對(duì)象忽你。
垃圾回收算法
Mark-and-Sweep(標(biāo)記清除算法)
- 標(biāo)記:從根節(jié)點(diǎn)集合開始掃描幼东,標(biāo)記所有存活對(duì)象;
- 回收:回收不可達(dá)對(duì)象
-
碎片化
標(biāo)記清除算法
Copying(復(fù)制算法)
- 將堆分為對(duì)象面和空閑面-
- 新生成對(duì)象存放在對(duì)象面
- 對(duì)象面滿之后將存活對(duì)象移動(dòng)到空閑面
- 將對(duì)象面所有對(duì)象內(nèi)存清除
適用于存活對(duì)象較少的場(chǎng)景(新生代)科雳,解決了碎片化問題根蟹,但浪費(fèi)了50%的堆空間。
Mark-and-Compacting (標(biāo)記整理算法)
- 標(biāo)記:和標(biāo)記清楚相同糟秘;
-
整理:移動(dòng)所有存活對(duì)象简逮,按照內(nèi)存地址依次排列,然后將末端內(nèi)存地址以后的內(nèi)存全部回收尿赚。
解決了碎片化問題散庶,不用浪費(fèi)百分之50的空間。
標(biāo)記整理算法
分代收集算法
按照對(duì)象生命周期的不同劃分區(qū)域以采用不同的垃圾回收算法
堆內(nèi)存劃分.png
GC分類:Minor GC(用于年輕代)凌净,F(xiàn)ull GC(用于老年代)悲龟。
年輕代
- 包含一個(gè)Eden區(qū)兩個(gè)Survivor區(qū),
- 每當(dāng)一個(gè)Eden區(qū)對(duì)象滿時(shí)泻蚊,觸發(fā)一次Minor GC躲舌,Eden和from Survivor的存活對(duì)象復(fù)制到to Survivor區(qū)。
- 清除Eden區(qū)和from Survivor區(qū)的對(duì)象的內(nèi)存空間性雄。
- 每經(jīng)歷一次GC没卸,對(duì)象的年齡+1
- 默認(rèn)年齡為15,對(duì)象移動(dòng)到老年代秒旋,可以用參數(shù) -XX: +MaxTenuringThreshold設(shè)置
- 可以用參數(shù) -XX:+PretenuerSizeThreshold來設(shè)置新生成大對(duì)象大小约计,超過該大小的對(duì)象直接存放到老年代。
常見的調(diào)優(yōu)參數(shù)
- -XX:SurvivorRatio:Eden和Survivor的比值 8:1
- -XX:NewRatio:老年代和年輕代內(nèi)存大小的比例 2:1
老年代
- 存放生命周期較長(zhǎng)的對(duì)象
- 通常采用標(biāo)記清除算法或者標(biāo)記整理算法
- Full GC 比 Mionr GC 慢迁筛,但頻率低
- 觸發(fā)Full GC的條件:
1煤蚌、老年代空間不足;
2细卧、永久代空間不足(Java7之前)尉桩;
3、CMS GC時(shí)出現(xiàn) promotion failed, concurrent mode failure
4贪庙、Minor GC晉升到老年代的平均大小大于老年代的剩余空間
5蜘犁、調(diào)用系統(tǒng)的system.gc()
Stop-the-World:JVM由于執(zhí)行GC而停止了應(yīng)用程序的執(zhí)行;多數(shù)GC通過減少Stop-the-World發(fā)生的時(shí)間來提高程序的性能
Safepoint:分析過程中對(duì)象引用關(guān)系不會(huì)發(fā)生變化的點(diǎn):產(chǎn)生Safepoint的地方:方法調(diào)用止邮;循環(huán)跳轉(zhuǎn)这橙;異常跳躍。
常見的垃圾收集器
JVM的運(yùn)行模式
- Server:?jiǎn)?dòng)慢导披,啟動(dòng)后運(yùn)行快
- Client:?jiǎn)?dòng)快屈扎,啟動(dòng)后運(yùn)行慢
年輕代垃圾收集器
Serial 收集器 -XX: +UseSerialGC,復(fù)制算法
-
單線程收集撩匕,進(jìn)行垃圾收集時(shí)鹰晨,必須暫停所有的工作
Serial 收集器.png
ParNew 收集器 -XX:+UseParNewGC,復(fù)制算法
- 多線程收集止毕,其他同Serial相同
- 單核執(zhí)行效率不如Serial并村,在多核下才有優(yōu)勢(shì),因?yàn)榫€程上下文切換的開銷
- 默認(rèn)情況下滓技,線程數(shù)和CPU核數(shù)相同
Parallel Scavenge收集器 -XX:+UseParallelGC哩牍,復(fù)制算法
- 更加關(guān)注系統(tǒng)的吞吐量
- 在多核下更有優(yōu)勢(shì),Server模式下默認(rèn)的年輕代收集器
- -XX:+UseAdaptiveSizePolicy 內(nèi)存調(diào)優(yōu)交給虛擬機(jī)
老年代常用的垃圾處理器
Serial Old收集器 -XX: +UseSerialOldGC令漂,標(biāo)記-整理算法
1膝昆、單線程收集,進(jìn)行垃圾收集時(shí)叠必,暫停所有線程
2荚孵、簡(jiǎn)單高效,client模式下默認(rèn)的老年代收集器
Parallel Old -XX:+UseParallelOldGC纬朝,標(biāo)記-整理算法
1收叶、多線程,吞吐量?jī)?yōu)先
Parallel Scavenge + Parallel Old
CMS收集器 -XX:+UseConcMarkSweepGC共苛,標(biāo)記-清除算法
- 初始化標(biāo)記:(stop the world)
從GC Root掃描與 Root 對(duì)象直接關(guān)聯(lián)的對(duì)象 - 并發(fā)標(biāo)記:并發(fā)追溯標(biāo)記判没,程序不會(huì)停頓
- 并發(fā)預(yù)清理:查找并發(fā)標(biāo)記階段從年輕代晉升到老年代的對(duì)象
- 重新標(biāo)記:暫停虛擬機(jī)蜓萄,掃描CMS堆中的剩余對(duì)象(stop the world)
- 并發(fā)清理:清理垃圾對(duì)象,程序不會(huì)停頓
- 并發(fā)重置:重置CMS收集器的數(shù)據(jù)結(jié)構(gòu)
碎片化
Garbage First收集器
并發(fā)核并行
分代收集
空間整合:標(biāo)記整理
可預(yù)測(cè)的停頓
將整個(gè)Java堆內(nèi)存劃分為多個(gè)大小相等的Region澄峰,年輕代和老年代不再物理隔離