垃圾收集機(jī)制
- 需要被收集的垃圾: 1.沒有引用指向的對象。2.兩個對象互相引用诲祸,且沒有外部引用指向他們。3. 多個對象環(huán)形引用而昨,形成一個閉環(huán)救氯,且沒有外部引用指向他們。
- 回收規(guī)則: 正向可達(dá) 算法歌憨。從roots對象計算可以到達(dá)的對象都不是垃圾着憨。root對象舉例:main方法中的創(chuàng)建的所有對象;java虛擬機(jī)啟動時的ClassLoader躺孝。
-
垃圾收集算法:
- Mark-Sweep 標(biāo)記算法:沒有被引用的對象一一標(biāo)記出來享扔,GC運(yùn)行時進(jìn)行清除。缺點(diǎn):清除后內(nèi)存不連續(xù)植袍、碎片化惧眠。 空和不空的內(nèi)存塊互相間隔著,若有一個比較大的對象進(jìn)入時于个,有可能找不到可以存下它的連續(xù)整塊內(nèi)存氛魁。這時會觸發(fā)fullGC,全部回收厅篓,壓縮秀存,再存下新對象。影響效率羽氮。
- Copying 復(fù)制算法:內(nèi)存被平成兩個連續(xù)的區(qū)域或链。永遠(yuǎn)有一個內(nèi)存區(qū)是空著的,回收被使用的一塊內(nèi)存時档押,直接把存活對象全部拷貝到空著的一塊內(nèi)存區(qū)中澳盐,并清空本內(nèi)存區(qū)祈纯。內(nèi)存復(fù)制的效率很高,并保證了內(nèi)存塊的連續(xù)性叼耙。缺點(diǎn):內(nèi)存浪費(fèi)腕窥,永遠(yuǎn)只能用一半。
java堆內(nèi)存的 新生代 中垃圾收集時用的是復(fù)制算法筛婉。新生代分成了三塊內(nèi)存區(qū):Eden簇爆、 Survivor0、Survivor1爽撒。GC運(yùn)行時按正向可達(dá)規(guī)則將Eden中存活對象復(fù)制到S0內(nèi)存塊中入蛆,并清除當(dāng)前內(nèi)存塊,下一次GC時匆浙,將S0和Eden中存活的對象復(fù)制到S1中安寺,清除Eden和S0,如此往復(fù)首尼。內(nèi)存大小比例為8:1 : 1挑庶。 因為對象創(chuàng)建時最初存放于eden 而90%以上的對象往往在方法結(jié)束后被回收,留下的很少软能,故S0和S1比例可遠(yuǎn)小于Eden迎捺。 ps:堆內(nèi)存的性能優(yōu)化方式可參考:
- Mark-Compact 標(biāo)記壓縮 被標(biāo)記的對象回收后,把存活對象壓縮到一起查排,留下連續(xù)的內(nèi)存塊凳枝。缺點(diǎn):效率低于copy算法
java堆內(nèi)存的 老年代 中垃圾收集時一般用的是標(biāo)記壓縮法。老年代中新產(chǎn)生的垃圾較少跋核,但是堆積的垃圾可能很多岖瑰,故標(biāo)記壓縮的在該內(nèi)存塊下效率不會太低,也保證了內(nèi)存空間不浪費(fèi)砂代。
-
引用的類型: 強(qiáng)引用蹋订;軟引用;弱引用刻伊;虛引用露戒。
- 經(jīng)常使用的
String a = new String("abc")
都為強(qiáng)引用,即使內(nèi)存不夠時捶箱,只要引用存在智什,都不會被清除,此時就報OutOfMemory丁屎。 - 軟引用
SoftReference<Bitmap> softBitmap = new SoftReference<Bitmap>();
該引用在內(nèi)存不夠的情況下會被強(qiáng)制清除荠锭。如在讀取大量圖片的應(yīng)用場景中,如果每次讀取圖片都從硬盤讀取晨川,則會嚴(yán)重影響性能节沦,但是如果全部加載到內(nèi)存當(dāng)中键思,又有可能造成內(nèi)存溢出。此時就可以使用軟引用的方式來存取圖片甫贯。 - 弱引用。只要發(fā)生垃圾回收看蚜,都會被清除
- 經(jīng)常使用的
END