[转]java垃圾回收之循环引用
工作原理:為每個內(nèi)存對象維護(hù)一個引用計數(shù)。
當(dāng)有新的引用指向某對象時就將該對象的引用計數(shù)加一,當(dāng)指向該對象的引用被銷毀時將該計數(shù)減一,當(dāng)計數(shù)歸零時,就回收該對象所占用的內(nèi)存資源。
缺陷:在每次內(nèi)存對象被引用或引用被銷毀的時候都必須修改引用計數(shù),這類操作被稱為footprint。引用計數(shù)的footprint是很高的。這使得程序整體的性能受到比較大的影響。因此多數(shù)現(xiàn)代的程序語言都不適用引用計數(shù)作為垃圾收集的實(shí)現(xiàn)算法。
另外,引用計數(shù)還有一個致命的缺陷,當(dāng)程中出現(xiàn)序循環(huán)引用時,引用計數(shù)算法無法檢測出來,被循環(huán)引用的內(nèi)存對象就成了無法回收的內(nèi)存。從而引起內(nèi)存泄露。
?
舉例說明就是:
?
class A{public B b;} class B{public A a; } public class Main{public static void main(String[] args){A a = new A();B b = new B();a.b=b;b.a=a;} }?
在函數(shù)的結(jié)尾,a和b的計數(shù)均為2
?
先撤銷a,然后a的計數(shù)為1,在等待b.a對a的引用的撤銷,也就是在等待b的撤銷
對于b來講,也是同理
兩個對象都在等待對方撤銷,所有這兩個資源均不能釋放
?
?
- 標(biāo)記-清除(Mark-Sweep)
此算法執(zhí)行分兩階段。第一階段從引用根節(jié)點(diǎn)開始標(biāo)記所有被引用的對象,第二階段遍歷整個堆,把未標(biāo)記的對象清除。此算法需要暫停整個應(yīng)用,同時,會產(chǎn)生內(nèi)存碎片。 - 復(fù)制(Copying)
此算法把內(nèi)存空間劃為兩個相等的區(qū)域,每次只使用其中一個區(qū)域。垃圾回收時,遍歷當(dāng)前使用區(qū)域,把正在使用中的對象復(fù)制到另外一個區(qū)域中。次算法每次只處理正在使用中的對象,因此復(fù)制成本比較小,同時復(fù)制過去以后還能進(jìn)行相應(yīng)的內(nèi)存整理,不過出現(xiàn)"碎片"問題。當(dāng)然,此算法的缺點(diǎn)也是很明顯的,就是需要兩倍內(nèi)存空間。 - 標(biāo)記-整理(Mark-Compact)
此算法結(jié)合了"標(biāo)記-清除"和"復(fù)制"兩個算法的優(yōu)點(diǎn)。也是分兩階段,第一階段從根節(jié)點(diǎn)開始標(biāo)記所有被引用對象,第二階段遍歷整個堆,把清除未標(biāo)記對象并且把存活對象"壓縮"到堆的其中一塊,按順序排放。此算法避免了"標(biāo)記-清除"的碎片問題,同時也避免了"復(fù)制"算法的空間問題。 - 增量收集(Incremental Collecting)
實(shí)施垃圾回收算法,即:在應(yīng)用進(jìn)行的同時進(jìn)行垃圾回收。不知道什么原因JDK5.0中的收集器沒有使用這種算法的。 - 分代(Generational Collecting)
基于對對象生命周期分析后得出的垃圾回收算法。把對象分為年青代、年老代、持久代,對不同生命周期的對象使用不同的算法(上述方式中的一個)進(jìn)行回收。現(xiàn)在的垃圾回收器(從J2SE1.2開始)都是使用此算法的。
- 標(biāo)記-清除(Mark-Sweep)
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/lihaozy/archive/2013/06/08/3125974.html
總結(jié)
以上是生活随笔為你收集整理的[转]java垃圾回收之循环引用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [翻译]NUnit---Descript
- 下一篇: GridView的 使用