開門見山,常見的GC(垃圾回收)算法有以下四種,本文重在解析GC算法,是爲講解垃圾回收器做知識鋪墊。至於分代回收將在其它文章中補充說明。
目錄:
1. 引用計數法(Java沒有采用)
2. 標記-清除法 (jvm老年代回收)
3. 標記-壓縮法 (jvm老年代回收)
4. 複製算法 (jvm新生代回收)
5. 幾種算法對比
至於新生代和老年代的說法會在本文第4-5點簡要介紹
1. 引用計數法(Java沒有采用)
每個對象有一個引用計數屬性,新增一個引用時計數加1,引用釋放時計數減1,計數爲0時可以回收。此方法簡單,但無法解決對象相互循環引用的問題,如下圖所示。
①當出現左邊綠色的情況時,假設外部對A的引用消除,此時因爲A引用計數從1減爲0,A將被清除。從而對B的引用也消除,B的計數減爲0,GC將正確回收對象{A, B}
②然而若出現右邊橙色狀況,假設外部對E的引用消除,外部對於對象集{C,D,E}不再有引用,但他們之間出現循環引用現象,計數始終保持爲1,導致{C,D,E}無法被回收。
2. 標記-清除法
(這部分是我在課程展示時做的ppt講的,在原ppt上有動畫和僞代碼對比演示,以及如何對掃描整個堆的標記-清除法作出優化,想要擴展的可以點擊鏈接下載)
標記-清掃式垃圾回收器是一種直接的全面停頓算法。簡單的說,它們找出所有不可達的對象,並將它們放入空閒列表Free。
清掃過程將分爲標記階段和清掃階段。以下是結合僞代碼的詳細分析。
①首先把根集所引用的對象reached(可達標誌位)設爲1,這裏假設根集引用了o1和o4,並將其加入到未掃描集合Unscanned中。至於根集是一組必須活躍的引用,比如所有活躍棧幀裏指向GC堆裏對象的引用(即正在被調用的引用類型參數和局部變量等)。
對於根集的更多詳情可查看引文:對於根集的理解
② 刪除未掃描集合中的某個對象o1,並找到o1所引用的對象o3和o8;(原書寫的刪除對象並找到引用,我認爲是先找到引用再刪除,可能有翻譯上的誤差)
再將o3和o8的reached標誌位設爲1,並將o3和o8放入未掃描集合中;
(未掃描集合中的對象表示是可達的,它們都可以被直接或間接引用)
③和以上步驟類似,此時刪除未掃描集合中的引用對象如o4,找出o4所引用的對象,改變被引用對象的標誌位爲1並放入未掃描集合。重複以上操作,直到Unsanned集合爲空,同時所有直接或間接引用的對象的 reached 位都被標記爲1,進入清掃階段;
④清掃所有 reached 標誌位爲0的對象(沒有被直接或間接訪問過),被清掃對象放入Free集合中;
⑤將存活的對象 reached 標誌位歸還位0,進行下一輪標記-清掃工作。
清理效果如圖所示:
缺點:需要掃描整個堆區,時間開銷較大。感興趣的可以查看我上傳的ppt中,標記-清除法的優化版。
3. 標記-壓縮法
總體思想和標記-清除法類似
①標記階段,通過根節點標記所有可達(直接或間接可訪問)對象,和標記-清除法類似;
②清除階段,將上一輪存活對象壓縮到內存的一端,之後清理邊界。(如此一來可以減少內存碎片,避免分配大對象時空間不夠)
清理效果如圖所示!
4. 複製算法
在堆區中,對象分爲新生代(年輕代)、老年代和永生代,而複製算法發生是發生在新生代的。新建的對象一般分配在新生代的Eden區,當Eden快滿時進行一次小型的垃圾回收。存活的對象會移動到 Survivor1區(以下簡稱S1)。
當再次發生 GC 時,S1區的存活對象將複製到先前閒置的S2區,同時存活對象壽命+1;以後每次發生GC,S1和S2區將交替的作爲存活對象的存放區和閒置區。並且如果存活對象的壽命達到某個閾值,它將被分配到老年代中。(注意在JDK8中已經沒有老年代的概念,使用的是metaspace的概念,感興趣請參考 jdk8 Metaspace 調優)
爲什麼需要年輕代:
按照GC的運行機制,會回收掉已經死掉的對象,而對象一般都是在年輕代就會死去,所以年輕代比老年代需要更頻繁的GC清理,下面針對年輕代與老年代的回收機制有不同的講解
存在的問題:
空間浪費,需要整合標記。所以大對象一般不放在複製空間,直接進入老年代。
5. 幾種算法對比
複製算法與標記-壓縮法對比:
複製收集算法在對象存活率較高時就要執行較多的複製操作,效率將會變低。更關鍵的是,如果不想浪費50%的空間,就需要有額外的空間進行分配擔保,以應對被使用的內存中所有對象都100%存活的極端情況,所以複製算法僅僅應用在新生代,而老年代一般不能直接選用這種算法,使用標記-壓縮法。
標記-壓縮法與標記-清除法對比:
根據老年代的特點,有人提出了“標記-壓縮”(Mark-Compact)算法,標記過程仍然與“標記-清除”算法一樣,但後續步驟不是直接對可回收對象進行清理,而是讓所有存活的對象都向一端移動,然後直接清理掉端邊界以外的內存。也可以減少內存碎片。
---------------------------------------------------------------------------------------------------------------------------------------------------
感謝您的觀看!
參考資料和圖片來源: