JVM 垃圾回收算法

pengjiang 8年前發布 | 6K 次閱讀 Java開發

來自: http://my.oschina.net/u/1041012/blog/616142


 


對象可觸及性算法

可觸及性算法是判斷對象是否死亡的最基本的算法。所謂死亡對象就是內存堆中不再使用的對象。 
用于被GC回收的對象。

引用計數算法 Reference Counting

引用計數法是給對象中添加一個引用計數器,每當有一個地方引用它時,計數器加1, 
當引用失效時,計數器減1;任何時候計算器都為0的對象就是不可觸及的對象。

Reference Counting 判定效率高,實現簡單。 
微軟的COM,ActionScript3,FlashPlayer3,Python 都采用Reference Counting來計算

Java 語言中沒有采用這個算法的主要原因是,它難以解決循環引用的問題。

根搜索算法 GC Root Tracing

基本思路就是就是通過一系列名為 GC Root 的對象作為起始點,從這些節點開始向下搜索, 
搜索走過的路勁作為引用鏈,當一個對象到GC Root 沒有任何引用鏈時,則證明此對象不可觸及

GC Root 包括以下幾種

  • 虛擬機棧中的引用的對象

  • 方法區中的類靜態屬性引用的對象

  • 方法區中的常量引用的對象

  • 本地方法棧中JNI的引用的對象。

垃圾回收算法

標記-清楚算法 Mark-Sweep

標記-清楚算法是最基本的算法,其算法分為兩個階段,標記階段和清除階段。 
首先標記出所需要回收的對象,標記完成后統一收掉所有的被標記的對象。

他的缺點主要有兩個:

  • 效率問題,標記和清除的效率都不高

  • 空間問題,標記清除后會產生大量的碎片內存

復制算法 Copying

為了解決效率問題,復制算法將可用內存分為大小相等的兩塊,每次只用其中一塊。 
當一塊內存用完了,就將還存活著的對象復制到另外一塊上面,然后把已用過的內存空間一次清理掉。

內存分配不用考慮碎片等復雜情況,只要移動堆頂指針,實現簡單,運行高效。只是這種算法的代價是將內存縮小為原來的一半。

** 
在實際應用中,不會簡單的把所有存活對象從一邊拷貝到另外一邊,經過優化,會把大對象放到老生代的內存區域中,這一動作其實就是內存分配擔保的一個動作(Handle Promotion)。 
我們沒有辦法保證每次需要復制的內存對象 在另一塊區域一定夠,這時需要借一塊區域通常來說是老年代存放,在清理之后在放回去,或者說就長期放在老年代了。 
**

標記-壓縮算法 Mark-Compact

標記-壓縮算法是 標記-清除算法的一種優化,標記過程仍然一樣,但后續步驟不是直接對可回收對象進行清理,而是讓所有存活的對象都向一端移動,然后直接清理掉端邊界以外的內存。

分代收集 General Collection

所謂分代收集其實是各種回收算法的綜合應用。根據對象的存活周期的不同將內存劃分為幾塊。一般是把Java堆分為新生代和老年代。 
新生代中,每次垃圾收集時都要發現大批對象死去,只有少量存活,那就選用復制算法,只需付出少量存活對象的復制。 
而老年代中因為對象的存活率高,沒有額外的空間對它進行分配擔保,就必須使用標記清理或者壓縮算法。

 

 本文由用戶 pengjiang 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!