在JAVA里,可作為GC Roots的對象包括:
1、虛擬機棧(棧幀中的本地變量表)中的引用的對象
2、方法區(qū)中的類靜態(tài)屬性引用的對象
3盖淡、方法區(qū)中的常量引用的對象
4、本地方法棧中JNI的引用的對象
無用的類判定條件
1凿歼、該類所有的實例都已經被回收
2褪迟、加載該類的classloader已經被回收
3、該類對應的java.lang.Class對象沒有在任何地方被引用答憔,無法在任何地方通過反射訪問該類的方法牵咙。
垃圾收集算法
標記-清除算法
分為標記和清除兩個階段,首先標記出所有需要回收的對象攀唯,在標記完成后統(tǒng)一回收掉所有被標記的對象洁桌。主要缺點有兩個:一個是效率問題,標記和清除過程的效率都不高侯嘀;另一個是空間問題另凌,標記清除后會產生大量不連續(xù)的內存碎片。
復制算法
為了解決效率問題戒幔,復制算法將內存容量劃分為大小相等的兩塊吠谢,每次只使用其中的一塊。當這一塊的內存用完了诗茎,就將還存活著的對象復制到另外一塊上面工坊,然后把已使用過的內存空間一次清理掉。將內存分為一塊較大的Eden空間和兩塊較小的survivor空間敢订,每次使用Eden和其中的一塊Survivor王污,當回收時,將Eden和Survivor中還存活著的對象一次性copy到另外一塊survivor空間上楚午,然后清理掉Eden和剛才使用過的Survivor空間昭齐。Eden:Survivor=8:1
標記-整理算法
復制收集算法在對象存活率較高時就要執(zhí)行較多的復制操作,效率將會變低矾柜,更關鍵的是如果不想浪費50%的空間阱驾,就需要額外的空間進行分配擔保,以應對被使用的內存中所有對象都100%存活的極端情況怪蔑,所以在老年代一般不能直接選用這種算法里覆。根據老年代的特點,有人提出標記-整理算法缆瓣,標記過程與標記-清除算法一樣喧枷,但后續(xù)步驟不是直接對可回收對象進行清理,而是讓所有存活對象都向一端移動,然后直接清理掉端邊界以外的內存割去。
分代收集算法
根據新生代老年代的特點采用最適當的算法窟却。
垃圾收集器
Serial收集器
新生代的單線程收集器昼丑,用一個線程完成垃圾收集工作呻逆,在收集期間stop the world,直到它收集結束菩帝。Serial收集器對于 運行在client模式下是一個很好的選擇咖城。
ParNew收集器
Serial收集器的多線程版本,除了使用多線程進行垃圾收集之外呼奢,其余行為包括Serial收集器可用的所有控制參數宜雀、收集算法、STW握础、對象分配規(guī)則辐董、回收策略都與Serial收集器完成一樣。運行在server模式下虛擬機首選的新生代收集器
Parallel Scavenge收集器
新生代收集器禀综,也是使用復制算法并行的多線程收集器简烘,它的關注點與其他收集器不同,CMS等關注點是盡可能縮短垃圾收集時用戶線程的停頓時間定枷,而Par Scavenge的目標則是達到一個可控制的吞吐量孤澎。吞吐量 = 運行用戶代碼時間/(運行用戶代碼時間+垃圾收集時間)
Serial Old收集器
Serial收集器的老年代版本,單線程欠窒,使用標記-整理算法覆旭,Client模式下虛擬機使用。如果在server模式下岖妄,主要有兩大用途:一個是與Parallel Scavenge收集器搭配使用型将,另一個就是作為CMS收集器的后備預案,在并發(fā)收集發(fā)生concurrent mode failure時使用荐虐。
Parallel Old收集器
Parallel Scavenge收集器的老年代版本茶敏,多線程標記-整理算法
CMS收集器
一種以獲取最短回收停頓時間為目標的收集器。運行過程分為4個步驟
1缚俏、初始標記
2惊搏、并發(fā)標記
3、重新標記
4忧换、并發(fā)清除
其中初始標記地回、重新標記這兩步驟仍然需要STW,初始標記僅僅只是標記一下GC Roots能直接關聯(lián)到的對象腹暖,速度很快抢呆,并發(fā)標記階段就是進行GC Roots Tracing的過程,而重新標記則是為了修正并發(fā)標記期間,因用戶程序繼續(xù)運行而導致標記產生變動的那一部分對象的標記記錄碗暗,這個階段的停頓時間一般會比初始標記階段稍長一些颈将,但遠比并發(fā)標記的時間短。
由于整個過程中耗時最長的并發(fā)標記和并發(fā)清除過程中言疗,收集器都可以與用戶線程一起工作晴圾,所以總體來說CMS的內存回收過程是與用戶線程一起并發(fā)地執(zhí)行的。
G1收集器
G1收集器是基于標記-整理算法實現(xiàn)的收集器噪奄,不產生空間碎片死姚,能讓使用者明確指定在一個長度為M毫秒的時間片段內,消耗在垃圾收集上的時間不得超過N毫秒勤篮。G1將整個JAVA堆劃分為多個大小固定的獨立區(qū)域都毒,并且跟蹤這些區(qū)域里面的垃圾堆積程序,在后臺維護一個優(yōu)先表碰缔,每次根據允許的收集時間账劲,優(yōu)先回收垃圾最多的區(qū)域。
大多數情況下金抡,對象優(yōu)先在Eden分配瀑焦,當Eden區(qū)沒有足夠的空間進行分配時將發(fā)起一次Minor GC。
大對象直接進入老年代竟终,虛擬機提供了一個-XX:PretenureSizeThreshold參數蝠猬,令大于這個設置值的對象直接在老年代中分配 。這樣做的目的是避免在Eden及兩個Survivor區(qū)之間發(fā)生大量的內存拷貝统捶。