前文知道了哪些對象應(yīng)該被刪除燥筷,那么本文就談?wù)勗趺磩h除,也就是刪除所用的算法肆氓。
標(biāo)記-清除算法
從名字可知算法分為兩個(gè)階段谢揪,先是標(biāo)記出所有需要被回收的對象蕉陋,然后再把這些被標(biāo)記的對象進(jìn)行清除凳鬓。但該算法有兩個(gè)缺點(diǎn):標(biāo)記和清除操作的效率不高;清除以后會產(chǎn)生大量不連續(xù)的碎片空間,碎片太多導(dǎo)致以后分配較大對象時(shí)匹颤,導(dǎo)致內(nèi)存不足從而提前觸發(fā)新的一次垃圾收集行為仅孩。
復(fù)制算法
為了解決效率問題杠氢,復(fù)制算法將內(nèi)存分為大小相同的兩塊站刑,每次只使用其中一塊,垃圾收集時(shí)摆尝,將使用的那一塊(假設(shè)為A)中存活著的對象復(fù)制到另一塊(假設(shè)為B)堕汞,然后將使用的塊A進(jìn)行清空勺爱,然后使用塊B琐鲁,下一次收集,塊B中存活的對象復(fù)制給塊A围段,塊B清空投放,如此反復(fù)。這種算法也有問題涝桅,本來可以使用空間大小被縮小到了一半,代價(jià)有點(diǎn)高冯遂。
標(biāo)記-整理算法
與標(biāo)記-清除算法類似谒获,先是對需要回收的對象進(jìn)行標(biāo)記,然后將存活的對象挪到一起寻定,待回收的對象挪到一起精耐,將存活對象之外的空間進(jìn)行清空。好處是減少了不連續(xù)的碎片空間卦停,但標(biāo)記加上對象挪動,效率依舊不高
分代收集算法
目前商業(yè)虛擬機(jī)都使用這種算法僵芹,這種算法結(jié)合了之前的三種算法小槐,但使用更靈活荷辕,讓之前的算法的缺點(diǎn)不那么明顯件豌,首先先來了解下java堆的組成結(jié)構(gòu)
堆
heap.png
- 堆分為新生代Young generation茧彤、老年代Old generation和永久代Perm
- 新生代用來存放新生的對象(98%的對象都是朝生夕滅)骡显,約占堆內(nèi)存的三分之一惫谤,其中新生代又劃分為Eden和from survivor和to survivor,比例為8:1:1
- 老年代用來存活年齡較大的對象,新生代中的對象達(dá)到一定“年齡”后還存活則會移入老年代
- 持久代主要存放類定義险污、字節(jié)碼和常量等很少會變更的信息
了解了java堆以后,我們就結(jié)合堆的知識來理解算法拯腮。
當(dāng)對象被創(chuàng)建以后,被創(chuàng)建在新生代的Eden上动壤,當(dāng)Eden內(nèi)存不足時(shí)會觸發(fā)Minor GC淮逻,若對象在第一次GC后依舊存活,則被移動from survivor空間哼丈,并設(shè)年齡為1,下一次Minor GC發(fā)生時(shí)醉旦,from survivor中的對象通過復(fù)制算法桨啃,將存活著的對象復(fù)制到to survivor并清空from survivor,存活的對象年齡+1匈棘,之前的to survivor變成from survivor析命,from survivor變成to survivor逃默。
當(dāng)survivor中對象年齡達(dá)到了一定的閥值(默認(rèn)為15)队秩,會從survivor移到老年代Old generation中昼浦。但也不一定,如果在survivor空間中相同年齡所有對象大小的總和大于survivor空間的一半鸟蟹,年齡大于等于該年齡的對象都可直接進(jìn)入老年代使兔。
老年代中對象不受Minor GC的影響,當(dāng)老年代內(nèi)存不足時(shí)或者無法為大內(nèi)存對象找到連續(xù)的空間時(shí)會發(fā)生Major GC虐沥,Major GC并不會頻繁發(fā)生。Major GC 使用標(biāo)記-清除算法镐依,會產(chǎn)生大量碎片天试,這些碎片需要整理,Major需要花較長時(shí)間务唐。當(dāng)老年代內(nèi)存不夠時(shí),會產(chǎn)生Out Of Memory異常枫笛。 - Minor GC 發(fā)生在新生代的垃圾收集被稱為Minor GC刚照,使用的是復(fù)制算法,發(fā)生頻繁
- Major GC 發(fā)生在老年代的垃圾收集被稱為Major GC海诲,使用的是標(biāo)記-清除算法,不容易發(fā)生,發(fā)生之前通常會發(fā)生Minor GC闸昨。
- Full GC 指的是整個(gè)堆的垃圾回收蚯斯,包括Major GC和Major GC拍嵌,但不一定就是兩者相加的和遭赂,需看具體產(chǎn)品的實(shí)現(xiàn)