本文內容來自《深刻理解Java虛擬機》,主要是自身學習,用於記錄重點,方便回憶,複習。對應《深刻理解Java虛擬機》第三章,記錄GC的算法,特色,經常使用GC收集器。算法
虛擬機系列一:Java虛擬機以內存bash
垃圾回收器的主要做用是回收無用的對象空間,那麼怎麼判斷對象是否已經無用了呢??主要有兩種算法。多線程
對象增長一個計數器,當有引用(變量)指向該對象是,計數器加一,但引用再也不指向該對象,計數器減一,計數器爲0便可回收。Java虛擬機未使用該方法,主要是因爲該方法很難解決循環應用問題。以下:併發
class GcTest{
Object obj;
public static void main(){
GcTest objA = new GcTest(); GcTest objB = new GcTest();
objA.obj = objB; objB.obj = objA;
objA = null;
objB = null;
//此種狀況下使用,應用計數法,對象objA,objB的計數均爲1,未能被回收
}
}複製代碼
從CG Roots出發,向下搜索,所走過的路徑稱爲引用鏈,當一個對象沒有在任何引用鏈上,則此對象可被回收。post
GC Roots的對象包括如下引用:學習
(1)虛擬機棧(方法中局部變量指向的引用)中引用的對象。spa
(2)方法區中類靜態屬性引用的對象。線程
(3)方法區中常量引用的對象。code
(4)本地方法區棧中JNI應用的對象。對象
補充:
可達性分析不可達的對象不會當即被回收,還得進過兩次標記過程。一、第一次標記爲篩選對象是否必要執行finalize()方法(對象沒有覆蓋finalize,或已經執行過則爲非必要)。二、若是1結果爲必要,則放入F-Queue隊列中,虛擬機會創建低優先機線程調用,不保證必定執行完finalize(是對象最後的復活機會)。
相似Object obj = new Object(),不會被垃圾回收器回收。
有用但非必須的對象,在系統將要發生內存溢出前,把這些對象列進回收範圍,進行第二次回收。經過SofeReference類實現。
非必須對象,強度比軟引用弱,發生垃圾回收,不管內存是否足夠,都會回收對象。經過WeakReference實現
幽靈引用、幻影引用,最弱的一種引用。惟一的用處是,垃圾回收時會收到一個系統通知,經過PhantomReference實現。
標記出內存中可被回收的對象,回收相應的對象。主要有兩個不足:一、效率問題,標記、清除效率都不高。二、空間碎片化,會有大量不連續的內存碎片。
將內存劃分爲大小相等的兩塊、一塊爲空閒面,一塊爲對象面。回收是減對象面中不能被回收的對象複製到空閒面,清除對象面內全部對象。此時的清除後的塊爲空閒面。使用於對象存活率低場景,少許複製,清除全部空間。
對不能被回收的對象進行標記,整理到連續的空間上,清除掉餘下空間。
採用分代收集算法,把Java堆分爲年輕代、老年代。年輕代中每次回收都只有少許對象存活,適用「複製算法」。老年代存活率高、適用標記整理算法。
年輕代中分爲Eden區,還有兩塊Survivor區。
每次建立對象,使用Eden區及一塊Survivor區。當垃圾回收時,將對象複製到另外一塊Survivor區,清除該Eden區及Survivor區數據。HotSpot虛擬機默認Eden:Survivor大小比例爲8:1,也就是一塊Survivor只有空間10%,回收時,當Eden區大量對象存活時,Survivor明顯放不下。這時對象會被放入老年區。
進入老年區除以上狀況還有,Survivor區中數據通過15次(默認,可配置)垃圾回收,仍未被回收,會將對象放入老年區。
新生代垃圾收集器: Serial(1) ParNew(2) Parallel Scavenage(3)
老年代垃圾收集器: CMS(可配合的新生的收集器爲一、2) Serial Old(可配合的新生的收集器爲一、二、3) Parallel Old(可配合的新生的收集器爲3)
單線程收集器,工做時,必須暫停其餘全部工做線程。Client模式下的默認年輕代(新生代)收集器,簡單高效。
Serial收集器的多線程版,指定參數-XX:UseConcMarkSweepGC選項後,默認新生代收集器就會是ParNew,經過-XX:ParallelGCThreads限制垃圾收集器線程數。
吞吐量(運行用戶代碼時間/cpu時間(垃圾收集器工做時間+用戶代碼運行時間))優先的收集器。適合後臺運算而不須要太多交互任務。-XX:MaxGCPauseMillis控制垃圾收集器最大停頓時間,-XX:GCTimeRatio((0,100)整數,工做時間/垃圾時間,如19 ,則工做時間佔比爲19/19+1 )吞吐量大小。-XX:+UseAdaptiveSizePolicy虛擬機會根據系統狀況自動調整各參數。
serial的老年代收集器,單線程、標記-整理算法。
Parallel Scavenage,多線程、標記-整理算法,吞吐量優先。
追求停頓時間短、標記-清除算法、過程包括:
一、初始化標記(Stop The World 中止工做線程)
二、併發標記
三、從新標記(Stop The World 中止工做線程)
四、併發清除
缺點:標記-整理算法,容易碎片化。
配置參數
-XX:+UseCMSCompactAtFullCollection ,頂不住,須要Full GC時開啓內存合併整理。
-XX:+CMSFullGCsBeforeCompaction 設置多少次不壓縮的Full GC後進行GC壓縮,默認爲0,即每次Full GC都進行碎片整理。
複製+標記-整理,總體複製-整理算法,局部複製算法