掃二維碼與項目經(jīng)理溝通
我們在微信上24小時期待你的聲音
解答本文疑問/技術(shù)咨詢/運營咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流
在 JVM 中,有兩個非常重要的知識點,一個是 JVM 的內(nèi)存布局(JVM 運行時的數(shù)據(jù)區(qū)域),另一個就是垃圾回收。而垃圾回收中又有兩個重要的知識點,一個是如何確定 JVM 中的垃圾對象,另一個是使用不同的垃圾收集器進(jìn)行垃圾回收。而本篇要討論的是前者,后面的內(nèi)容咱們下一篇再聊。

垃圾(死亡)對象的判定有兩種常用的算法:引用計數(shù)器算法和可達(dá)性分析算法。
引用計數(shù)算法(Reference Counting) 屬于垃圾收集器的早期實現(xiàn)算法了,它指的是在創(chuàng)建對象時關(guān)聯(lián)一個與之相對應(yīng)的計數(shù)器,當(dāng)此對象被使用時加 1,相反銷毀時 -1。當(dāng)此計數(shù)器為 0 時,則表示此對象未使用,可以被垃圾收集器回收。
引用計數(shù)算法的優(yōu)缺點很明顯,其優(yōu)點是垃圾回收比較及時,實時性比較高,只要對象計數(shù)器為 0,則可以直接進(jìn)行回收操作;而缺點是無法解決循環(huán)引用的問題,比如以下代碼:
public class RefCounterTest {
// 對象 A
static class RefObjectA {
private RefObjectB refObjectB;
public void setRefObjectB(RefObjectB refObjectB) {
this.refObjectB = refObjectB;
}
}
// 對象 B
static class RefObjectB {
private RefObjectA refObjectA;
public void setRefObjectA(RefObjectA refObjectA) {
this.refObjectA = refObjectA;
}
}
// 測試代碼
public static void main(String[] args) {
RefObjectA objectA = new RefObjectA();
RefObjectB objectB = new RefObjectB();
objectA.setRefObjectB(objectB);
objectB.setRefObjectA(objectA);
objectA = null;
objectB = null;
}
}如以上代碼所示,即使是將 main 方法中的 objectA 和 objectB 都設(shè)置為 null,也就是這兩個對象都徹底不使用了,但是因為二者存在相互引用的關(guān)系,所以它們所對應(yīng)的對象計數(shù)器不為 0,這樣循環(huán)引用導(dǎo)致垃圾數(shù)據(jù)無法被清除的事件就產(chǎn)生了。
可達(dá)性分析算法(Reachability Analysis) 是目前主流虛擬機(jī)中,使用最廣泛的判斷垃圾對象的實現(xiàn)算法,它指的是從對象的起點(GC Roots)開始向下搜索,如果對象到 GC Roots 沒有任何引用鏈相連時,也就是說此對象到 GC Roots 不可達(dá)時,則表示此對象可以被垃圾回收器所回收,如下圖所示:
在 Java 語言中,可作為根節(jié)點(GC Roots)的對象有以下 4 類:
不管是引用計數(shù)法還是可達(dá)性分析算法都與對象的“引用”有關(guān),這說明對象的引用決定了對象的生死,而 Java 中的引用也比較復(fù)雜,它從 JDK 1.2 之后,(引用)分成了以下 4 種類型:
垃圾對象的判定有兩種常用的算法:引用計數(shù)器算法和可達(dá)性分析算法。其中引用計數(shù)器算法實現(xiàn)簡單、運行高效,但是存在循環(huán)引用的問題,所以主流的虛擬機(jī)使用的都是可達(dá)性分析算法,可達(dá)性分析算法是從對象的根節(jié)點 GC Roots 向下搜索,如果根節(jié)點相連就是正常的對象,否則為垃圾對象可以被垃圾回收器回收。

我們在微信上24小時期待你的聲音
解答本文疑問/技術(shù)咨詢/運營咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流