轉(zhuǎn)載、引用請(qǐng)標(biāo)明出處
http://www.itdecent.cn/p/8ec0ee8ca7ee
本文出自zhh_happig的簡書博客,謝謝
以下內(nèi)容,是本人學(xué)習(xí)的筆記和工作中的總結(jié),僅供大家參考,有誤的地方還請(qǐng)指正
一 判定垃圾對(duì)象算法
-
引用計(jì)數(shù)法
- 在對(duì)象中添加一個(gè)計(jì)數(shù)器,記錄著指向?qū)ο蟮囊玫膫€(gè)數(shù)
- 當(dāng)有新的引用指向這個(gè)對(duì)象的時(shí),計(jì)數(shù)器+1,當(dāng)指向?qū)ο蟮囊帽恢胣ull時(shí),計(jì)數(shù)器-1
- 當(dāng)計(jì)數(shù)器的值為0,那么這個(gè)對(duì)象就是垃圾對(duì)象,就會(huì)被垃圾回收器回收
- 缺陷:當(dāng)對(duì)象1中有引用指向?qū)ο?,對(duì)象2中有引用指向?qū)ο?,但是再也沒有其他外部引用指向?qū)ο?和對(duì)象2,對(duì)象1、對(duì)象2是垃圾對(duì)象。通過引用計(jì)數(shù)法,對(duì)象1、對(duì)象2計(jì)數(shù)器都為1,不會(huì)被垃圾回收器回收。
- 不推薦使用
-
可達(dá)性分析法
- 該算法的基本思路就是通過GC Roots對(duì)象作為起點(diǎn),從這些節(jié)點(diǎn)開始向下搜索
- 搜索走過的路徑被稱為引用鏈
- 當(dāng)一個(gè)對(duì)象,從GC Roots節(jié)點(diǎn)向下搜索,沒有任何一條路徑能夠達(dá)到該對(duì)象,那么這個(gè)對(duì)象就是垃圾對(duì)象
- 可以做為GC Roots的對(duì)象包括
- 虛擬機(jī)棧中引用指向的對(duì)象
- 方法區(qū)中類靜態(tài)屬性所引用的對(duì)象
- 方法區(qū)中常量所引用的對(duì)象
- 本地方法棧中引用的對(duì)象
二 垃圾回收算法
-
標(biāo)記-清除算法
- 分為標(biāo)記和清楚2步
- 標(biāo)記:就是通過可達(dá)性分析法將對(duì)象標(biāo)記為垃圾對(duì)象
- 清除:將垃圾對(duì)象回收
- 缺點(diǎn):存在效率問題和空間問題
- 垃圾對(duì)象在堆內(nèi)存中是散亂的,被清除之后,會(huì)導(dǎo)致越來越多不連續(xù)的空間,當(dāng)分配大對(duì)象時(shí),要尋找一片合適的內(nèi)存空間,就會(huì)變得困難
- 如果找不到合適的內(nèi)存空間存放這個(gè)大對(duì)象,就會(huì)觸發(fā)一次GC,影響性能
-
復(fù)制算法
- 年輕代的垃圾收集算法,在年輕代對(duì)象存活率低,復(fù)制算法效率很高
- 將堆內(nèi)存分成2部分,只在其中一部分中分配內(nèi)存
- 垃圾回收后,把存活的對(duì)象復(fù)制到另一部分內(nèi)存連續(xù)的空間上
- 就這樣在2個(gè)內(nèi)存中循環(huán)復(fù)制,這樣解決了 標(biāo)記-清除算法 中的效率問題
- 缺點(diǎn):由于只在其中一部分中分配內(nèi)存,存在內(nèi)存浪費(fèi)問題
- 再將內(nèi)存細(xì)分,即可降低內(nèi)存浪費(fèi),詳見Eden、Survivor 0 、Survivor 1、Tenured
-
標(biāo)記-整理算法
- 年老代的垃圾收集算法
- 在年老代對(duì)象存活率高,復(fù)制算法效率低,使用標(biāo)記-整理算法
- 標(biāo)記過程仍然與“標(biāo)記-清除”算法一樣,
- 整理:不是直接清除,而是對(duì)內(nèi)存里面的對(duì)象進(jìn)行重新整理,讓所有存活的對(duì)象都向一端移動(dòng),依次排列,那么端邊界另一邊的就都是垃圾對(duì)象了,直接清理掉
- 標(biāo)記-整理算法唯一的缺點(diǎn)就是效率也不高,不僅要標(biāo)記所有存活對(duì)象,還要整理所有存活對(duì)象的引用地址。從效率上來說,標(biāo)記-整理算法要低于復(fù)制算法。
-
分代收集算法
- 根據(jù)不同的內(nèi)存區(qū)選擇不同的算法
- 在年輕代,選擇復(fù)制算法
- 在年老代,選擇標(biāo)記-整理算法
三 垃圾回收器
-
Serial
- 年輕代垃圾收集器,采用復(fù)制算法
- 串行收集器:如果serial要收集垃圾,必須讓程序其他線程停掉,收集完畢,程序其他線程繼續(xù)執(zhí)行
- 單線程垃圾收集器:serial單線程收集垃圾
- 整體效率低
-
Serial Old
- 它是Serial收集器的年老代版本,與Serial相似,區(qū)別是使用“標(biāo)記-整理”算法
-
Parnew
- 年輕代垃圾收集器,采用復(fù)制算法
- 串行收集器:如果parnew要收集垃圾,必須讓程序其他線程停掉,收集完畢,程序其他線程繼續(xù)執(zhí)行
- 多線程垃圾收集器:parnew多線程收集垃圾
-
Parallel scavenge
- 與parnew類似,區(qū)別是parallel scavenge能控制吞吐量
- 吞吐量 = 執(zhí)行用戶代碼的時(shí)間 / (執(zhí)行用戶代碼的時(shí)間 + 垃圾回收所占用的時(shí)間)
- -xx:MaxGCPauseMillis 垃圾收集器停頓最大時(shí)間,就是垃圾收集線程(多線程)收集垃圾的時(shí)間,是不是設(shè)置越小就越好呢?假設(shè)設(shè)置100ms,垃圾收集器分配的內(nèi)存可能是1G,設(shè)置為1ms,垃圾收集器分配的內(nèi)存可能只有10M,因?yàn)橹挥?0M這么小的內(nèi)存才能在1ms內(nèi)收集完,那么10M內(nèi)存顯然太小了,就會(huì)造成垃圾頻繁回收。原來100ms回收一次的任務(wù),現(xiàn)在如果1ms回收一次,可能要頻繁回收80次,對(duì)比之下性能并沒有多大提升。所以不是設(shè)置的越小越好,應(yīng)該更具實(shí)際情況設(shè)置一個(gè)合理值。
- -xx:CGTimeRatio 吞吐量大小
- 適用注重吞吐量的后端服務(wù)
-
Parallel Old
- 是Parallel Scavenge收集器的年老代版本,與Parallel Scavenge相似,但與Parallel Scavenge不同的是,它使用的是“標(biāo)記-整理算法”
- 使用方式:-XX:+UseParallelOldGC,打開該收集器后,將使用Parallel Scavenge(年輕代)+Parallel Old(年老代)的組合進(jìn)行GC
-
CMS
- 年老代、永久代垃圾收集器,采用標(biāo)記-清除算法
- 并行收集器:垃圾收集線程可以和程序其他線程并發(fā)執(zhí)行
- 多線程垃圾收集器:CMS多線程收集垃圾
-
工作過程
- 初始標(biāo)記:造成程序其他線程停頓。標(biāo)記垃圾對(duì)象
- 并發(fā)標(biāo)記:與程序線程并發(fā)運(yùn)行。在運(yùn)行期間會(huì)發(fā)生對(duì)象的引用變更等等情況,對(duì)于這些對(duì)象,都是需要進(jìn)行重新標(biāo)記的,否則會(huì)發(fā)生漏標(biāo)的情況。這個(gè)階段因?yàn)槭遣l(fā)的容易導(dǎo)致concurrent mode failure
- 重新標(biāo)記:會(huì)造成程序其他線程停頓。重新標(biāo)記的內(nèi)存范圍是整個(gè)堆,包含young_gen和old_gen。為什么要掃描新生代呢,因?yàn)閷?duì)于老年代中的對(duì)象,如果被新生代中的對(duì)象引用,那么就會(huì)被視為存活對(duì)象,即使新生代的對(duì)象已經(jīng)不可達(dá)了。所以需要標(biāo)記young_gen和old_gen。
- 并發(fā)清理:與程序線程并發(fā)運(yùn)行。并發(fā)清理階段用戶線程還在運(yùn)行著,伴隨程序運(yùn)行自然就還會(huì)有新的垃圾不斷產(chǎn)生,這一部分垃圾出現(xiàn)在標(biāo)記過程之后,CMS無法在當(dāng)次收集中處理掉它們,只好留待下一次GC時(shí)再清理掉。這一部分垃圾就稱為“浮動(dòng)垃圾”。
- 并發(fā)重置:與程序線程并發(fā)運(yùn)行。重新設(shè)置CMS算法內(nèi)部的數(shù)據(jù)結(jié)構(gòu),準(zhǔn)備下一個(gè)CMS生命周期的使用
- 優(yōu)點(diǎn)
- 并發(fā)收集
- 低停頓:只有初始標(biāo)記和重新標(biāo)記會(huì)造成程序其他線程短暫停頓
- 缺點(diǎn)
- 占用大量的cpu資源
- 無法處理浮動(dòng)垃圾
- 出現(xiàn)Concurrent Mode Failure
- CMS收集與應(yīng)用線程會(huì)同時(shí)增加對(duì)堆內(nèi)存的占用,也就是說,CMS必須要在老年代堆內(nèi)存用盡之前完成垃圾回收,否則CMS回收失敗,出現(xiàn)Concurrent Mode Failure;
- 年老代的剩余空間無法滿足新對(duì)象的空間分配,也會(huì)出現(xiàn)這個(gè)錯(cuò)誤
- 在出現(xiàn)Concurrent Mode Failure時(shí),將觸發(fā)擔(dān)保機(jī)制,Serial Old收集器將會(huì)以STW的方式進(jìn)行一次full gc,從而造成較大停頓時(shí)間,影響性能
-
G1(Garbage First)
- JDK7增加,成為HotSpot重點(diǎn)發(fā)展的垃圾回收技術(shù),被HotSpot團(tuán)隊(duì)寄予取代CMS的使命
- 將會(huì)被安排成為JDK9的默認(rèn)垃圾收集器
- 并行收集器:垃圾收集線程可以和程序其他線程并發(fā)執(zhí)行
- 多線程垃圾收集器:G1多線程收集垃圾
- 詳見G1垃圾收集器
四 垃圾回收器作用內(nèi)存區(qū)域以及他們之間的組合關(guān)系

-
7種不同分代的收集器
- Serial、ParNew、Parallel Scavenge、Serial Old、Parallel Old、CMS、G1;
-
垃圾收集器所屬區(qū)域
- 年輕代收集器:Serial、ParNew、Parallel Scavenge
- 年老代收集器:Serial Old、Parallel Old、CMS
- 整堆收集器:G1
-
兩個(gè)收集器間有連線,表明它們可以搭配使用
- Serial/Serial Old
- Serial/CMS
- ParNew/Serial Old
- ParNew/CMS
- Parallel Scavenge/Serial Old
- Parallel Scavenge/Parallel Old
- G1
以上內(nèi)容,是本人學(xué)習(xí)的筆記和工作中的總結(jié),僅供大家參考,有誤的地方還請(qǐng)指正
轉(zhuǎn)載、引用請(qǐng)標(biāo)明出處
http://www.itdecent.cn/p/8ec0ee8ca7ee
本文出自zhh_happig的簡書博客,謝謝
