判斷對(duì)象是否存活
-
引用計(jì)數(shù)算法
定義: 給對(duì)象中添加一個(gè)引用計(jì)數(shù)器,每當(dāng)有地方對(duì)其進(jìn)行引用,計(jì)數(shù)器數(shù)值加1,當(dāng)引用失效時(shí)啊片,計(jì)數(shù)器就減1,任何時(shí)刻計(jì)數(shù)器為0的對(duì)象就是不可能再被使用的袭异。
但是Java虛擬機(jī)中并沒(méi)有使用計(jì)數(shù)算法來(lái)管理內(nèi)存,因?yàn)樗茈y解決對(duì)象之間相互循環(huán)引用的問(wèn)題炬藤。如下代碼中這種相互引用御铃,導(dǎo)致引用計(jì)數(shù)一直不為0
public class RefrenceGC(){
public Object instance = null;
public static void testGC(){
RefrenceGC objA = new RefrenceGC();
RefrenceGC objB = new RefrenceGC();
objA.instance = objB;
objB.instance = objA;
objA = null;
objB = null;
}
}
-
可達(dá)性分析算法
在主流的商用程序語(yǔ)言(Java,C#,Lisp)的主流實(shí)現(xiàn)中,都是稱通過(guò)可達(dá)性分析來(lái)判定對(duì)象是否存活沈矿。
思路: 通過(guò)一系列稱為“GC Roots”的對(duì)象作為起始點(diǎn)上真,從這些節(jié)點(diǎn)開(kāi)始向下搜索,搜索走過(guò)的路徑稱為引用鏈(Reference Chain)羹膳,當(dāng)一個(gè)對(duì)象到GC Roots沒(méi)有任何引用鏈相連時(shí)(用圖論的話來(lái)說(shuō)睡互,就是從GC Roots到這個(gè)對(duì)象不可達(dá)),則證明此對(duì)象是不可用的陵像。
圖中對(duì)象object5,object6,object7雖然相互有關(guān)聯(lián)就珠,但是它們到GC Roots是不可達(dá)的撇吞,因?yàn)樗鼈儗?huì)被判定為可回收對(duì)象凿试。
生存還是死亡
即使在可達(dá)性分析后的不可達(dá)對(duì)象即舌,也不是“非死不可”僻弹,如果要真正宣告死亡冶伞,至少經(jīng)歷兩次標(biāo)記過(guò)程:如果對(duì)象在進(jìn)行可達(dá)性分析后發(fā)現(xiàn)沒(méi)有與GC Roots相連接的引用鏈丙躏,就會(huì)被第一次進(jìn)行標(biāo)記并且進(jìn)行一次刪選谚攒,判斷是否有必要執(zhí)行finalize()方法鸡典,當(dāng)對(duì)象沒(méi)有覆蓋finalize()方法腰耙,或者finalize()方法已經(jīng)被虛擬機(jī)調(diào)用過(guò)榛丢,即會(huì)被判為沒(méi)有必要執(zhí)行。
如果被判定為有必要執(zhí)行的finalize()方法挺庞,對(duì)象將會(huì)被放置在F-Queue的隊(duì)列中晰赞,會(huì)有個(gè)低優(yōu)先級(jí)的Finalizer線程去執(zhí)行,finalize()方法是對(duì)象逃脫死亡命運(yùn)的最后一次機(jī)會(huì),如果要拯救自己宾肺,就需要重新與引用鏈上的任意一個(gè)對(duì)象建立起關(guān)聯(lián)即可溯饵。
垃圾收集算法
標(biāo)記-清除算法
對(duì)需要回收的進(jìn)行標(biāo)記,然后清除標(biāo)記對(duì)象锨用。
缺點(diǎn):
1丰刊、效率低,標(biāo)記和清除兩個(gè)過(guò)程的效率都不高
2增拥、空間問(wèn)題啄巧,標(biāo)記清除后產(chǎn)生大量不連續(xù)的內(nèi)存碎片,在下次分配較大的對(duì)象時(shí)掌栅,無(wú)法找到足夠的連續(xù)內(nèi)存而不得不提前觸發(fā)另一次垃圾回收秩仆。
復(fù)制算法
將內(nèi)存按照等容量分為兩塊,每次只使用其中一塊猾封,一塊用完澄耍,將還存活的復(fù)制到另一塊上,然后進(jìn)行整塊清除晌缘。
缺點(diǎn):內(nèi)存縮為原來(lái)的一半
商業(yè)化虛擬機(jī)采用此種方式齐莲,不按標(biāo)準(zhǔn)的1:1劃分,而是劃分一塊大的Eden 和兩塊小的Survivor空間磷箕,每次使用Eden和一塊小的Survivor,使用完选酗,將存活的復(fù)制到另一塊小的Survivor上,然后清除Eden和那塊Survivor岳枷。默認(rèn)Eden 和Survivor比為8:1芒填。
標(biāo)記-整理算法
標(biāo)記后,讓所有存活的往一端移動(dòng)空繁,直接清理端邊界外面的內(nèi)存
分代收集算法
一般劃分為新生代和老年代殿衰,新生代少量對(duì)象存活,采用復(fù)制算法盛泡,老年代對(duì)象存活率高播玖,采用標(biāo)記-清除或者標(biāo)記-整理方法去處理。