回收方法
- 引用計(jì)數(shù)算法:
給對(duì)象中添加一個(gè)引用計(jì)數(shù)器浩村,每當(dāng)有一個(gè)地方引用它時(shí)露戒,計(jì)數(shù)器+1,當(dāng)引用失效白嘁,計(jì)數(shù)器-1.任何時(shí)刻計(jì)數(shù)器為0的對(duì)象就是不可能再被使用的坑鱼。
- 優(yōu)點(diǎn):實(shí)現(xiàn)簡(jiǎn)單,判定效率高效权薯,被actionscript3和python中廣泛應(yīng)用姑躲。
- 缺點(diǎn):無法解決對(duì)象之間的相互引用問題。java沒有采納
- 可達(dá)性分析算法:
通過一系列稱為“GC Roots”的對(duì)象作為起始點(diǎn)盟蚣,從這些節(jié)點(diǎn)開始向下搜索黍析,搜索所走過的路徑稱為引用鏈,當(dāng)一個(gè)對(duì)象到GCRoots沒有任何引用鏈相連的時(shí)候屎开,則證明此對(duì)象是不可用的阐枣。
比如如下,右側(cè)的對(duì)象是到GCRoot時(shí)不可達(dá)的奄抽,可以判定為可回收對(duì)象蔼两。
回收依據(jù)
在java中,可以作為GCRoot的對(duì)象包括以下幾種:
- 虛擬機(jī)棧中引用的對(duì)象逞度。
- 方法區(qū)中靜態(tài)屬性引用的對(duì)象额划。
- 方法區(qū)中常量引用的對(duì)象。
- 本地方法中JNI引用的對(duì)象档泽。
那么是不是這些對(duì)象就非死不可俊戳,也不一定,此時(shí)只能宣判它們存在于一種“緩刑”的階段馆匿,要真正的宣告一個(gè)對(duì)象死亡抑胎。至少要經(jīng)歷兩次標(biāo)記:第一次:對(duì)象可達(dá)性分析之后,發(fā)現(xiàn)沒有與GCRoots相連接渐北,此時(shí)會(huì)被第一次標(biāo)記并篩選阿逃。第二次:對(duì)象沒有覆蓋finalize()方法,或者finalize()方法已經(jīng)被虛擬機(jī)調(diào)用過赃蛛,此時(shí)會(huì)被認(rèn)定為沒必要執(zhí)行恃锉。
如何回收
-
標(biāo)記清除法(Mark-Sweep)
標(biāo)記清除法是垃圾回收算法的思想基礎(chǔ)。標(biāo)記清除算法將垃圾分為兩個(gè)階段:標(biāo)記階段和清除階段呕臂。
標(biāo)記階段淡喜,通過根節(jié)點(diǎn),標(biāo)記所有從根節(jié)點(diǎn)開始的可達(dá)對(duì)象诵闭,未標(biāo)記過的對(duì)象就是未被引用的垃圾對(duì)象。
清除階段,清除所有未被標(biāo)記的對(duì)象疏尿。
-
復(fù)制算法(Copying)
復(fù)制算法是瘟芝,將原有的內(nèi)存空間分為兩塊,每次只使用其中一塊褥琐,在垃圾回收時(shí)锌俱,將正在適用的內(nèi)存中存活對(duì)象復(fù)制到未使用的內(nèi)存塊,然后清除使用的內(nèi)存塊中所有的對(duì)象敌呈。
-
標(biāo)記壓縮算法(Mark-Compact)
標(biāo)記壓縮算法是一種老年代的回收算法贸宏。
標(biāo)記階段和標(biāo)記清除算法一致,對(duì)可達(dá)對(duì)象做一次標(biāo)記磕洪。
清理階段吭练,為了避免內(nèi)存碎片產(chǎn)生,將所有的存活對(duì)象壓縮到內(nèi)存的一端析显。
- 分代收集算法
GC分代的基本假設(shè):絕大部分對(duì)象的生命周期都非常短暫鲫咽,存活時(shí)間短。
“分代收集”(Generational Collection)算法谷异,把Java堆分為新生代和老年代分尸,這樣就可以根據(jù)各個(gè)年代的特點(diǎn)采用最適當(dāng)?shù)氖占惴āT谛律写踵冢看卫占瘯r(shí)都發(fā)現(xiàn)有大批對(duì)象死去箩绍,只有少量存活,那就選用復(fù)制算法尺上,只需要付出少量存活對(duì)象的復(fù)制成本就可以完成收集材蛛。而老年代中因?yàn)閷?duì)象存活率高、沒有額外空間對(duì)它進(jìn)行分配擔(dān)保尖昏,就必須使用“標(biāo)記-清理”或“標(biāo)記-整理”算法來進(jìn)行回收仰税。