引用計數(shù):一種簡單但速度很慢的垃圾回收技術(shù)
每個對象都含有一個引用計數(shù)器百新,當(dāng)有引用連接至對象時企软,計數(shù)器加1。但引用離開作用域或被置為 null 時饭望,引用計數(shù)減1仗哨。
- 管理引用計數(shù)的過程在整個程序生命周期中將持續(xù)發(fā)生。
- 如果對象之間存在循環(huán)引用铅辞,可能會出現(xiàn)“對象應(yīng)該被回收厌漂,但引用計數(shù)卻不為零”的情況。
Java垃圾回收器的思想
對于任何“活”的對象巷挥,一定能最終追溯到其存活在堆椬眩或靜態(tài)存儲區(qū)之中的引用。由此倍宾,如果從堆棧和靜態(tài)存儲區(qū)開始,遍歷所有的引用胜嗓,就能找到所有“活”的對象高职。對于發(fā)現(xiàn)的每個引用,必須追蹤它所引用的對象辞州,然后是此對象包含的所有引用怔锌,如此反復(fù)進(jìn)行,直到“根源于堆棧和靜態(tài)存儲區(qū)的引用”所形成的網(wǎng)絡(luò)全部被訪問為止变过。
基于這種思想埃元,Java虛擬機(jī)將采用一種自適應(yīng)的垃圾回收技術(shù)。有兩種工作方式媚狰。
停止-復(fù)制:先暫停程序的運(yùn)行(不屬于后臺回收模式)岛杀,然后將所有存活的對象從當(dāng)前堆復(fù)制到另一個堆,沒有被復(fù)制的全部都是垃圾崭孤。對于這種方式类嗤,效率會降低,存在兩個原因:
- 首先辨宠,得有兩個堆遗锣,然后得在這兩個分離的堆之間來回倒騰,從而得維護(hù)比實(shí)際需要多一倍的空間嗤形。Java虛擬機(jī)對此問題的處理方式是精偿,按需從堆中分配幾塊較大的內(nèi)存,復(fù)制動作發(fā)生在這些大塊內(nèi)存之間。
- 第二個問題在于復(fù)制笔咽。程序進(jìn)入穩(wěn)定狀態(tài)之后墓阀,可能只會產(chǎn)生少量垃圾,甚至沒有垃圾拓轻,盡管如此斯撮,復(fù)制式回收器仍然會將所有內(nèi)存自一處復(fù)制到另一處,這很浪費(fèi)扶叉。為了避免這種情形勿锅,Java虛擬機(jī)會進(jìn)行檢查:如果沒有新垃圾產(chǎn)生,就會轉(zhuǎn)換到另一種工作模式(即“自適應(yīng)”)枣氧;
標(biāo)記-清掃:從堆棧和靜態(tài)存儲區(qū)出發(fā)溢十,遍歷所有的引用,進(jìn)而找出所有存活的對象达吞。每當(dāng)它找到一個存活對象张弛,就會給對象設(shè)一個標(biāo)記,這個過程中不會回收任何對象酪劫。只有全部標(biāo)記工作完成的時候吞鸭,清理動作才會開始。在清理過程中覆糟,沒有標(biāo)記的對象將被釋放刻剥,不會發(fā)生任何復(fù)制動作。所以剩下的堆空間是不連續(xù)的滩字,垃圾回收器要是希望得到連續(xù)空間的話造虏,就得重新整理剩下的對象。