JVM|04垃圾回收

什麼是垃圾回收機制

背景知識

程序的運行必然須要申請內存資源,無效的對象資源若是不及時處理就會一直佔有內存資源,最終將致使內存溢出,因此對內存資源的管理是很是重要了。程序員

Java語言的垃圾回收

爲了讓程序員更專一於代碼的實現,而不用過多的考慮內存釋放的問題,因此,在Java語言中,有了自動的垃圾回收機制,也就是咱們熟悉的GC。
有了垃圾回收機制後,程序員只須要關心內存的申請便可,內存的釋放由系統自動識別完成。
換句話說,自動的垃圾回收的算法就會變得很是重要了,若是由於算法的不合理,致使內存資源一直沒有釋放,一樣也可能會致使內存溢出的。
固然,除了Java語言,C#、Python等語言也都有自動的垃圾回收機制。算法

Java的垃圾回收經常使用算法


引用計數法

原理

假設有一個對象A,任何一個對象對A的引用,那麼對象A的引用計數器+1,當引用失敗時,對象A的引用計數器就-1,若是對象A的計數器的值爲0,就說明對象A沒有引用了,能夠被回收。markdown

優劣分析

  1. 優點
    實時性較高,無需等到內存不夠的時候,纔開始回收,運行時根據對象的計數器是否爲0,就能夠直接回收。
    在垃圾回收過程當中,應用無需掛起。若是申請內存時,內存不足,則馬上報
    outofmember 錯誤。
    區域性,更新對象的計數器時,只是影響到該對象,不會掃描所有對象。jvm

  2. 劣勢
    每次對象被引用時,都須要去更新計數器,有一點時間開銷。
    浪費CPU資源,即便內存夠用,仍然在運行時進行計數器的統計。
    沒法解決循環引用問題。(最大的缺點)
    循環問題演示:
class TestA {
    public TestB b ;
}
class TestB{
    public TestA a;
}

public class Main {
    public static void main(String[] args) {
        TestA a = new TestA();
        TestB b = new TestB();
        a.b = b;
        b.a = a;
        a = null;
        b = null;
//     雖然被設置爲null,可是a與b之間依舊存在着循環引用的問題
    }
}

標記-清除算法

原理

標記清除算法,是將垃圾回收分爲2個階段,分別是標記和清除。
標記:從根節點開始標記引用的對象。
清除:未被標記引用的對象就是垃圾對象,能夠被清理。ide

JVM|04垃圾回收

初始狀態下,全部的目標對象都是爲0(未被標記)
待jvm出現有效內存耗盡,就會掛起線程,執行GC線程,進行標記性能

JVM|04垃圾回收

從根節點進行標記到最後,而後回收未被標記的對象。
清理完畢以後掛起gc線程,從新執行原先被掛起的線程。
而被標記的對象會被從新置0;優化

JVM|04垃圾回收
優劣分析線程

  1. 優點
    很明顯的解決了循環應用致使的不能被回收的問題3d

  2. 缺點
    缺點也很明顯
    效率較低,標記和清除兩個動做都須要遍歷全部的對象,而且在GC時,須要中止應用程序,對於交互性要求比較高的應用而言這個體驗是很是差的。
    經過標記清除算法清理出來的內存,碎片化較爲嚴重,由於被回收的對象可能存在於內存的各個角落,因此清理出來的內存是不連貫的

標記-壓縮算法

原理code

標記壓縮算法是在標記清除算法的基礎之上,作了優化改進的算法。和標記清除算法同樣,也是從根節點開始,對對象的引用進行標記,在清理階段,並非簡單的清理未標記的對象,而是將存活的對象壓縮到內存的一端,而後清理邊界之外的垃圾,從而解決了碎片化的問題。
JVM|04垃圾回收

優劣分析

  1. 優勢
    在標記清除算法的基礎上解決了產生碎片的問題

  2. 缺點
    算法多出一步壓縮,因此在性能上也會有所影響

複製算法

原理

複製算法的核心就是:將原有的內存空間一分爲二,每次只用其中的一塊,在垃圾回收時,將正在使用的對象複製到另外一個內存空間中,而後將該內存空間清空,交換兩個內存的角色,完成垃圾的回收。
典型的複製算法的落地實現就是:jvm中堆內存的年輕代的gc策略(具體能夠看我jvm系列的博客的內存模型的那一部份內容)

  1. 在GC開始的時候,對象只會存在於Eden區和名爲「From」的Survivor區,Survivor 區「To」是空的。

  2. 緊接着進行GC,Eden區中全部存活的對象都會被複制到「To」,而在「From」區中仍存活的對象會根據他們的年齡值來決定去向。年齡達到必定值(年齡閾值,能夠經過- XX:MaxTenuringThreshold來設置)的對象會被移動到年老代中,沒有達到閾值的對象會被複制到「To」區域。

  3. 通過此次GC後,Eden區和From區已經被清空。這個時候,「From」和「To」會交他們的角色,也就是新的「To」就是上次GC前的「From」,新的「From」就是上次GC前的「To」。無論怎樣,都會保證名爲To的Survivor區域是空的。

  4. GC會一直重複這樣的過程,直到「To」區被填滿,「To」區被填滿以後,會將全部象移動到年老代中。

優劣分析

  1. 優點
    在垃圾對象多的狀況下,效率較高
    清理後,內存無碎片

  2. 劣勢
    在垃圾對象少的狀況下,不適用,如:老年代內存
    分配的2塊內存空間,在同一個時刻,只能使用一半,內存使用率僅有50%

分代算法

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

相關文章
相關標籤/搜索