垃圾回收算法

1.垃圾對象判定標準

1.1 引用計數法

給對象加一個引用計數器,每當有一個地方引用它時計數器值就加1 ,當引用失效時,計數器值就減1,任何時刻計數器爲0的對象就不可能再被使用。

優點:效率高,大部分情況下都是一個不錯的算法(Java虛擬機沒有采用)

缺點:很難解決對象之間的相互循環引用的問題,比如 A 引用 B 對象中 b,B引用 A中心a ,將A或者B 重置爲Null, 並不能將計數器置爲0 ,這時候就無法進行gc 操作。

1.2可達性分析算法

主流商用語言(Java,C#)的主流實現中,都是通過可達性分析來判斷對象是否存活。基本思路是通過一系列的成爲"GC Roots"的對象作爲起始點,從這些節點開始向下搜索,搜索所有走過的路徑成爲引用鏈,當一個對象到GC Roots這個對象不可打時(就死從GC Roots到這個對象不可達),則證明沒有任何引用鏈項鍊,則證明對象是不可用的。在Java語言中,可作爲GCDRoots 的對象包括下面幾種

  • 虛擬機棧(棧楨中的本地變量表)中引用的對象
  • 方法區中靜態屬性引用的對象。
  • 方法區中常量引用的對象
  • 本地方法中JNI引用的對象(即一般會說的native方法)

2.生存還是死亡?

即使對象在可達分析算法中不可達,也並非是“非死不可”的,這時候他們暫時處於“緩刑”階段,要真正宣告一個對象死亡,至少要經歷兩次標記過程:

如果對象在進行可達性分析後發現沒有與GC Roots相連接的引用鏈,那它將會被第一次標記並且進行一次篩選,篩選的條件是此對象是否有必要執行finalize()方法。當對象沒有覆蓋finalize()方式或者finalize()方法已經被虛擬機調用過時,虛擬機將這兩種情況都視爲“沒必要執行”

如果這個對象被判定爲有必要執行finalize()方法,那麼這份對象將會放置在一個叫做F-Queue的隊列中,並在稍後有一個虛擬機自動簡歷的、地優先級的Finalizer線程去執行它,這裏所謂的“執行”是指虛擬機會觸發這個方法,但並不誠若會等待他允許結束,這樣做的原因是,如果一個對象在finalize()方法中執行緩慢,或者發生了死循環(更極端的情況),將可能會導致F-Queue對象中其他對象永久處於等待,甚至導致整個內存回收系統崩潰。finalzie()方法是對象逃脫死亡命運的最後一次機會,稍後GC將對F-Queue中的對象進行二次小規模的標記,如果對象要在finalize()中成功拯救自己—只要重新與引用鏈上的任何一個對象建立見習接,譬如把自己(this關鍵字)複製給某個類變量或者對象的成員變量,那在第二次標記時將被移除“即將回收”的集合,如果對象在這時候還沒有逃脫,那基本上它就真的被回收了。

3.垃圾回收算法

3.1.標記-清除(Mark-Sweep)

首先標記出需要回收的對象,在標記完成後統一回收所有被標記的對象。
優點:算法相對簡單,存活對象比較多的情況下效率較高

不足:需要掃描兩遍
(效率偏低,容易產生碎片)標記和清除兩個過程的效率都不高,另外標記清除之後會產生大量不連續的內存碎片,空間碎片太多可能會導致以後在程序運行過程中需要分配較大對象時,無法找到足夠的連續內存而不得不提前觸發另一次垃圾手機動作。

3.2 複製算法(copying) 需補充(eden,survivor,tenured)

將內存劃分爲大小相等的兩塊,每次只使用其中的一塊。當這一塊的內存用完了,就將還存活的對象複製到另一塊上面,然後再把已使用過的內存空間清理掉。這樣使得每次都是堆整個半區進行內存回收,內存分配時也就不需要考慮內存碎片等複雜情況,只要移動堆頂指針,按順序完成分配內存即可,實現簡單,運行高效。

優點:只掃描一次,效率提高了,沒有碎片,適用與存活對象比較少的場景

不足:(空間浪費,移動複製對象需要調整對象引用)這種算法的代價是將內存縮小爲了原來的一半,未免太高了點

3.3 標記-整理(Mark-Compact)

根據老年代的特點,標記過程仍與“標記-清除”算法一樣,但後續步驟不是直接堆可回收對象進行整理,而是讓所有存活的對象都向一端移動,然後直接清理掉端邊界一邊的內存。

優點:不會產生碎片,方便對象分配,不會產生內存減半問題

缺點:掃描兩次,需要移動對象,效率偏低

3.4 分代收集算法(Generational Collection)

當前商業虛擬機的垃圾手機都採用 分代收集算法,這種算法並沒有新的思想,只是根據對象存活週期的不同,將內存劃分爲幾塊。一般是把java堆分爲新生代和老年代,這樣就可以根據各自年代的特點採用最合適的收集算法。在新生代中,每次垃圾收集時都發現有大量對象死去,只有少量存活,那就選用複製算法,只需要付出少量存活對象的複製成本就可以完成收集。而老年代中因爲對象存活率高、沒有額外空間堆它進行分配擔保??,就必須使用“標記-清理”或者“標記-整理”算法來進行回收。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章