垃圾收集的意義
垃圾收集的出現(xiàn)解放了C++中手工對內(nèi)存進行管理的大量繁雜工作鸿竖,手工malloc,free不僅增加程序復(fù)雜度缚忧,還增加了bug數(shù)量。
分代收集朽肥。即在新生代和老生代使用不同的收集方式。在垃圾收集上蚁吝,目標主要有:加大系統(tǒng)吞吐量(減少總垃圾收集的資源消耗);減少最大STW(Stop-The-World)時間;減少總STW時間。不同的系統(tǒng)需要不同的達成目標框冀。而分代這一里程碑式的進步首先極大減少了STW,然后可以自由組合來達到預(yù)定目標温数。
可達性檢測
引用計數(shù):一種在jdk1.2之前被使用的垃圾收集算法,我們需要了解其思想够傍。其主要思想就是維護一個counter冕屯,當counter為0的時候認為對象沒有引用刹衫,可以被回收囱桨。缺點是無法處理循環(huán)引用。目前iOS開發(fā)中的一個常見技術(shù)ARC(Automatic Reference Counting)也是采用類似的思路窘面。在當前的JVM中應(yīng)該是沒有被使用的翠语。
根搜算法:思想是從gc root根據(jù)引用關(guān)系來遍歷整個堆并作標記,稱之為mark财边,等會在具體收集器中介紹并行標記和單線程標記肌括。之后回收掉未被mark的對象,好處是解決了循環(huán)依賴這種『孤島效應(yīng)』酣难。這里的gc root主要指:
a.虛擬機棧(棧楨中的本地變量表)中的引用的對象
b.方法區(qū)中的類靜態(tài)屬性引用的對象
c.方法區(qū)中的常量引用的對象
d.本地方法棧中JNI的引用的對象
整理策略
復(fù)制:主要用在新生代的回收上谍夭,通過from區(qū)和to區(qū)的來回拷貝。需要特定的結(jié)構(gòu)(也就是Young區(qū)現(xiàn)在的結(jié)構(gòu))來支持憨募,對于新生成的對象來說紧索,頻繁的去復(fù)制可以最快的找到那些不用的對象并回收掉空間。所以說在JVM里YGC一定承擔了最大量的垃圾清除任務(wù)菜谣。
標記清除/標記整理:主要用在老生代回收上珠漂,通過根搜的標記然后清除或者整理掉不需要的對象。
清除的過程
這里可以看到清除會產(chǎn)生碎片空間葛菇,對內(nèi)存利用不是很好甘磨,但不是說整理優(yōu)于清除,畢竟整理會更慢眯停。比如CMSGC就是使用清除而不是整理的济舆。
思考一下復(fù)制和標記清除/整理的區(qū)別,為什么新生代要用復(fù)制莺债?因為對新生代來講滋觉,一次垃圾收集要回收掉絕大部分對象,我們通過冗余空間的辦法來加速整理過程(不冗余空間的整理操作要做swap齐邦,而冗余只需要做move)椎侠。同時可以記錄下每個對象的『年齡』從而優(yōu)化『晉升』操作使得中年對象不被錯誤放到老年代。而反過來老年代偏穩(wěn)定措拇,我們哪怕是用清除我纪,也不會產(chǎn)生太多的碎片,并且整理的代價也并不會太大。
具體的垃圾收集器
新生代收集器:有Serial收集器浅悉、ParNew收集器趟据、Parallel Scavenge收集器
老生代收集器:Serial Old收集器、Parallel Old收集器术健、CMS收集器汹碱、G1收集器
Parallel Scavenge收集器:生代收集器荞估,使用復(fù)制算法咳促,并行多線程
Serial Old收集器:Serial收集器的老年代版本,單線程勘伺,使用標記-整理算法跪腹。
Parallel Old收集器:Parallel Scavenge收集器的老年代版本,多線程飞醉,使用標記-整理算法
CMS收集器:一種以獲取最短回收停頓時間為目標的收集器尺迂,基于“標記-清除”算法。運作過程分四個步驟:初始標記 冒掌、并發(fā)標記噪裕、重新標記、并發(fā)清除股毫。
G1的特點:并行與并發(fā)膳音、分代手機、空間整合铃诬、可預(yù)測的停頓
垃圾收集器大家庭
以上所有的垃圾收集器都會發(fā)生STW祭陷,只不過FGC的STW時間更長。
幾款重點研究的垃圾收集器:
CMSGC:
CMS(Concurrent Mark-Sweep)是以犧牲吞吐量為代價來獲得最短回收停頓時間的垃圾回收器趣席。對于要求服務(wù)器響應(yīng)速度的應(yīng)用上兵志,這種垃圾回收器非常適合,因此我們又叫它低延遲垃圾收集器宣肚。在啟動JVM參數(shù)加上-XX:+UseConcMarkSweepGC 想罕,這個參數(shù)表示對于老年代的回收采用CMS,注意此時新生代默認使用的是ParNew霉涨。CMS采用的基礎(chǔ)算法是:標記—清除按价。
MSCGC vs CMSGC
和普通序列化整理(MSC)區(qū)別在于有三個mark階段(實際上還有個預(yù)清理過程,但對于解釋清楚CMSGC沒有幫助就忽略了)笙瑟。CMSGC的精髓在于因為做到了不STW的情況下進行mark楼镐,我們得到了更短的總STW時間,代價是因為并行mark產(chǎn)生了『臟數(shù)據(jù)』即在mark的同時又生成了需要mark的對象往枷,我們必須再進行一次STW框产,并收尾(remark)凄杯。
同時,我們要注意到得到更短的STW的同時秉宿,我們犧牲了系統(tǒng)吞吐量盾舌,CMSGC總吞吐量比ParOld要更低。
G1GC
作為最新的垃圾收集器蘸鲸,有可能在jdk9中成為默認的垃圾收集器。
主要思路是將新生代老生代進一步分為多個region窿锉,每次gc可以針對部分region而不是整個堆內(nèi)存酌摇。由此可以降低stw的單次最長時間,代價是可能在總時間上會更高嗡载。
G1GC讓系統(tǒng)在整體吞吐量略降的情況下變得更加平滑穩(wěn)定窑多。
永久帶基本不參與垃圾回收,永久代滿了或者是超過了臨界值,會觸發(fā)完全Full GC
沒有最優(yōu)的g收集器洼滚,只有最適合的gc收集器埂息。