JVM ----垃圾回收的常見算法以及各自的優缺點 引用計數算法 標記清除算法 標記壓縮算法 複製算法 分代算法

前言

在學習垃圾回收算法之前要明白什麼是垃圾回收、爲什麼要做垃圾回收

程序的運行必然需要申請內存資源,無效的對象資源如果不及時處理就會一直佔有內存資源,最終將導致內存溢出,所以對內存資源的管理是非常重要了

下面我將逐個的分析每個算法的優缺點以及原理

引用計數算法

原理:

假設有一個對象A,任何一個對象對A的引用,那麼對象A的引用計數器+1,當引用失效時,對象A的引用計數器就-1,如果對象A的計數器的值爲0,就說明對象A沒有引用了,可以被回收

優點:

  • 實時性較高, 不需要等到內存不夠時纔回收
  • 在垃圾回收過程中, 應用不需要掛起。如果內存不夠時會報outofmember錯誤
  • 區域性, 跟新對象的計數器時, 只更新該對象, 不會掃描全面對象的

缺點:

  • 無法解決循環引用問題, 這是最大的缺陷, 下面說一下什麼是循環引用
class Person1{
  public Person2 person2;
}
class Person2{
  public Person1 person2;
}
public class Main{
    public static void main(String[] args){
        Person1 p1 = new Person1();
        Person2 p2 = new Person2();
        p1.person2=p2;
        p2.person1=p1;
        p1 = null;
        p2 = null;
    }
}

雖然a和b都爲null,但是由於a和b存在循環引用,這樣a和b永遠都不會被回收

標記清除算法

原理:

標記清除算法垃圾回收分爲兩個階段, 分別的標記和清除

  • 標記: 從根節點(GC Root)開始標記, 然後將所有的根節點(GC Root)可達的對象標記爲存活的對象。
  • 清除: 未被標記引用的對象就是垃圾對象, 可以進行回收
    在這裏插入圖片描述

優點

  • 解決了循環引用的問題, 沒有從root節點引用的對象都會被回收

缺點

  • 效率低, 因爲標記和清除兩個動作都要遍歷所有的對象, 並且在GC時, 需要停止應用程序
  • 清理出來的內存碎片化較爲嚴重, 因爲被回收的對象可能存在於內存的各個角落

標記壓縮算法

原理:

  • 標記壓縮算法是在標記清除算法的基礎之上,做了優化改進的算法。和標記清除算法一樣,也是從根節點開始,對對象的引用進行標記,在清理階段,並不是簡單的清理未標記的對象,而是將存活的對象壓縮到內存的一端,然後清理邊界以外的垃圾,從而解決 了碎片化的問題。
    在這裏插入圖片描述

優點

  • 標記壓縮算法是對標記清除算法的優化, 解決了碎片化的問題

缺點

  • 還是效率問題, 在標記清除算法上又多加了一步, 效率可想而知了

複製算法

原理:

  • 複製算法的核心就是,將原有的內存空間一分爲二,每次只用其中的一塊,在垃圾回收時,將正在使用的對象複製到另一個內存空間中,並以此排列, 然後將該內存空間清空,交換兩個內存的角色,完成垃圾的回收。
    在這裏插入圖片描述

優點:

  • 在垃圾多的情況下(新生代), 效率較高
  • 清理後, 內存無碎片

缺點:

  • 浪費了一半的內存空間
  • 在存活對象較多的情況下(老年代), 效率較差

分代算法
  • 前面介紹了多種回收算法,每一種算法都有自己的優點也有缺點,誰都不能替代誰,所以根據垃圾回收對象的特點進行選擇,纔是明智的選擇。
  • 分代算法其實就是這樣的,根據回收對象的特點進行選擇,在jvm中,年輕代適合使用復 制算法,老年代適合使用標記清除或標記壓縮算法

總結

巧幹能捕雄獅,蠻幹難捉蟋蟀。沒有最好的算法, 只有在合適的地方法使用合適的算法!

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