1. 程式人生 > >探索java回收機制

探索java回收機制

一、垃圾回收機制的意義
垃圾回收機制可以有效的防止記憶體的洩漏,有效的使用空閒的記憶體。
記憶體洩漏: 是指該記憶體空間使用完畢之後未回收,在不涉及複雜資料結構的一般情況下,java的記憶體洩漏表現為一個記憶體物件的生命週期超出了程式需要的它的時間長度。
垃圾回收功能:
(1) 定期發現那些物件不再被引用,並把這些物件佔據的堆空間釋放出來。
(2) 類似於作業系統的記憶體管理,垃圾收集器還需要處理由於物件動態生成與撤銷產生的堆碎塊,以便更有效的利用虛擬機器記憶體。
雖然說,Java語言規範沒有明確說明JVM使用哪種垃圾回收演算法,但是任何一種垃圾回收演算法一般要做兩件事情:(1) 發現無用的資訊物件 (2) 回收將無用物件佔用的記憶體空間。使該空間可被程式再次使用。

二、物件存活判斷
1. 引用計數演算法
1.1 演算法分析:
堆中每一個物件都有衣蛾引用計數。當新建立一個物件,或者有變數被賦值為這個物件的引用,則這個物件的引用計數加1;當一個物件的引用超過生存期或者被設定一個新的值時,這個物件的引用計數減1。當物件的引用計數變為0時,就可以被當作垃圾收集。
這種方法的好處是垃圾收集較快,適用於實時環境。缺點是這種方法無法檢測出迴圈引用。例如物件A引用物件B,物件B也引用物件A,則這兩個物件可能無法被垃圾收集器收集。
1.2 優缺點
優點: 引用計數收集器可以很快的執行,交織在程式執行中,對程式需要不被長時間打斷的實時環境比較有利。
缺點:無法檢測迴圈引用。如父物件有一個對子物件的引用,子物件反過來引用父物件。這樣,它們的引用計數永遠不可能為0.
1.3 引用計數器無法解決迴圈引用問題,例如:
這裡寫圖片描述


最後的兩句是將Objtect1 和 Object2 賦值為 NULL,也就是說 Objtect1 和 Object2 指向的物件已經不可能再被訪問,但是由於它們相互引用對方,導致它們的引用計數器都不為0,那麼垃圾收集器永遠不會回收它們。
2. 可達性分析演算法
將“GC Roots”演算法物件作為起始節點,向下搜尋,搜尋走過的路徑為引用鏈;當一個物件到GC Roots 沒有引用鏈時,則該物件時不可用的;
可作為“GC Roots”的物件:
(1)方法區中靜態屬性引用的物件
(2)方法區中常量引用的物件
(3)虛擬機器棧引用的物件(裝禎中本地變量表)
(4)本地方法棧中JNI引用的物件(Native)
三、 垃圾回收演算法
1. 標記-清除演算法
定義:先標記要回收的物件,然後統一回收。
適用:存活物件較多的垃圾回收。
缺點:
(1)效率低;標記和清除的過程效率不高;
(2)空間問題;標記清除後產生大量不連續的記憶體碎片,給大物件分配記憶體時沒有足夠連續的記憶體空間,導致提前觸發垃圾回收動作。
這裡寫圖片描述

2. 複製演算法
定義:將可用記憶體劃分成相等大小的兩塊,每次只使用其中一塊,當這一塊用完後將還存活的物件複製到另一塊。然後將已使用過的記憶體一次清理。
適用:存活物件較少的垃圾回收。
優點:每次對整個半區進行記憶體回收,不用考慮記憶體碎片問題,只要移動堆頂置針,按順序分配記憶體即可;實現簡單,執行高效。
缺點:將記憶體縮小了一半。
3. 標記-整理演算法
定義:先標記要回收的物件,將存活物件移動至另一端,最後清理端邊界以外的記憶體。
這裡寫圖片描述

4.  分代收集演算法
    定義:根據物件存活週期將記憶體劃分為新生代和老年代,然後根據每個年代的特點使用合適的回收演算法。
    如:新生代存活物件少可以採用複製演算法;老年代存活物件多並且分配擔保必須使用標記清理或標記整理回收演算法。

四、垃圾回收器
這裡寫圖片描述
1. Serial 收集器
定義:單執行緒收集器,收集時必須暫停其他所有使用者執行緒,直到收集結束。
適用:新生代
配置:
-xx:PretenureSizeThreadshold
-XX:HandlePromotionFailure
其他:
(1)單CPU環境Serial收集器沒有現成互動開銷,因此單執行緒的收集效率高。
(2)對於Client模式下的桌面應用,分配給虛擬機器的記憶體不會很大,對於一兩百兆的新生代記憶體回收停頓時間完全控制在一百多毫秒以內,停頓不頻繁發生,Serial收集器時最好的選擇。
(3)收集過程會暫停服務(Stop the world)
這裡寫圖片描述
2. ParNew收集器
定義:是Serial 收集器的多執行緒版本
適用:新生代
配置:
-XX:PretenureSizeThreshold
  -XX:HandlePromotionFailure
-XX:+UseConcMarkSweepGC (設定預設新生代收集器)
 -XX:+UserParNewGC (指定ParNew作為新生代收集器)
-XX:ParallelGCThreads(限制垃圾收集的執行緒數)
其他:
(1)與Serial 收集器的控制引數,收集演算法,Stop the world ,物件分配規則,回收策略完全一樣。
(2)是執行Server模式下虛擬機器首選新生代收集器(唯一能和CMS收集器配合的規則)
CMS 是兵法收集器,第一次實現讓收集執行緒和使用者執行緒同時工作;
CMS關注回收的停頓時間(暫停使用者執行緒時間),停頓時間越短越適合於使用者互動的程式,因為有較高的響應速度
(3)單CPU環境沒有Serial 收集器效率高
(4)並行的多執行緒收集器
這裡寫圖片描述
3, Parallel Scavenge 收集器
定義:和ParNew收集器一樣的收集器,區別在於主要關注吞吐量的控制和GC自適應調節策略;
注:吞吐量 = 執行使用者程式碼時間/(執行使用者程式碼時間+垃圾收集時間); 如果虛擬機器總共執行100分鐘,收集花費1分鐘,則吞吐量為99%
適用: 新生代;較高的吞吐量,導致高效的CPU利用率,主要適合後臺運算
配置:
-XX:MaxGCPauseMillis (控制回收停頓的最大時間 ; 注:時間越小會犧牲吞吐量和新生代空間)
  -XX:GCTimeRatio (設定吞吐量 0< X < 100 ; 垃圾回收時間佔總時間的比例, 吞吐量的倒數);如果將GCTimeRatio設定為19,最大GC時間佔總時間的5%(即1/(1+19));該值預設為99,則最大GC時間為1%    
-XX:+UseAdaptiveSizePolicy (開啟GC自適應調節策略) 
其中: GC自適應調節策略:虛擬機器根據當前系統性能,自動調節引數已提供最合適的時間和最大吞吐量;
調節的引數包括: (i)新生代大小(-Xmm),Eden 和 Survivor 空間比例(-xx:SurivivorRatio)
(ii)晉升老年代物件的年齡(-xx:PretenureSizeThreshold)
GC自適應調節策略將記憶體管理交給虛擬機器完成,只需要設定基本記憶體(-Xmx),停頓時間(MaxGCPauseMillis),吞吐量(GCTimeRatio)等引數給虛擬機器設立優化目標;
其他:
(1)並行:多條垃圾回收執行緒並行關注,單使用者執行緒處於等待狀態
並法:使用者執行緒和回收執行緒同時進行
(2)並行的多執行緒收集器
這裡寫圖片描述
4. Serial Old收集器
定義:是Serial 收集器的老年代版本的單執行緒收集器
適用:老年代(標記-整理演算法);主要給Client模式下的虛擬機器使用;

  1. Parallel Old收集器
    定義:是Parallel Scavenge收集器的老年代版本的多執行緒收集器
    使用:老年代(標記-整理演算法)
    6.CMS收集器(COncurrent Mark Sweep)
    定義:CMS是一款兵法收集,低停頓的收集器。
    關注目標:最短回收停頓時間。
    適用:網際網路站,B/S系統服務端(較快的響應速度,最短的系統停頓時間)較好的使用者體驗
    演算法:標記-清除
    回收步驟:
    (1)初始標記(標記GC Roots能直接關聯到的物件)(Stop the world)
    (2)兵法標記(進行GC Roots Tracing的過程)
    (3)重新標記(修正併發期間因使用者程式繼續執行而導致標記產生的物件的標記記錄)(stop the world)
    (4)併發清除
    執行時間:
    T(併發標記,併發清除)> T(重新標記) > T(初始標記)
    由於耗時最長的併發標記和併發清除和使用者執行緒一起工作,因此總體上CMS回收過程和使用者執行緒一起併發執行的。

  2. G1 收集器
    定義:一款面向服務端應用的垃圾收集器
    演算法:標記-整理
    特點:
    (1)並行與併發
    充分利用多CPU,多核環境縮短Stop the world 停頓時間,使用併發方式回收避免了GC時停頓Java執行緒
    (2)分代收集
    (3)空間整合(使用標記-整理 回收演算法,避免了大量空間回收碎片的產生)
    (4)可預測的停頓(G1在追求低停頓同時建立了可預測的停頓時間模型,可以讓使用者設定M毫秒內,GC所需要的時間不超過N毫秒)
    原理:
    1. G1 將新生代和老年代 分為大小相等的獨立區域,進行全區域垃圾回收,新生代和老年代不再是物理隔離,都是部分獨立區域的集合;
    2. 通過計算每個區域垃圾堆積的價值(回收可得到的空間/回收所需要的時間),然後根據價值大小有優先順序的進行垃圾回收,保證了回收的效率。‘
    3. 虛擬機發現獨立區域中的Reference型別資料進行寫操作時,判斷其他獨立區域是否有Reference資料引用的物件(即老年代物件是否引用了新生代物件),如果是就將引用資訊通過CardTable記錄到獨立區域的Remembered Set中,在垃圾回收的時候將Remembered Set加入到GC根節點的列舉範圍,可避免使用可達性演算法判斷物件存活而進行的全堆掃描,也避免有存活物件的遺漏。
    回收步驟:
     【1】初始標記(標記GC Roots能直接關聯到的物件,並修改TAMS(Next Top at Mark Start)的值,讓下一階段使用者程式併發執行時,能在正確的Region中建立物件)(Stop the World)
     【2】併發標記(從GC Roots開始對堆中物件可達性分析,找出存活物件)(和使用者執行緒併發進行)
    【3】最終標記(修正併發標記期間因使用者執行緒執行的而產生變動物件的標記記錄,虛擬機器將這些物件記錄到Remembered Set Logs中,然後合併到Rembered Set中)(Stop the World)
     【4】篩選回收(對每個獨立區域進行價值排序,根據使用者期望的GC停頓時間制定回收計劃)
    這裡寫圖片描述

五、回收器的組合使用
這裡寫圖片描述