深刻理解java:1.3. 垃圾收集

Java垃圾收集(Garbage Collection,GC)

 

某一個時點,一個對象若是有一個以上的引用(Rreference)指向它,那麼該對象就爲活着的(Live),java

不然死亡(Dead),視爲垃圾,可被垃圾回收器回收再利用。算法

 

垃圾回收操做須要消耗CPU、線程、時間等資源,因此容易理解的是垃圾回收操做不是實時的發生(對象死亡後不會立刻釋放),多線程

當內存消耗完或者是達到某一個指標(Threshold,使用內存佔總內存的比列)時,觸發垃圾回收操做。併發

 

GC須要完成的三件事情:.net

     哪些內存須要回收?線程

            --如何判斷對象已死?用 根搜索算法對象

            這個算法的基本思路就是經過一系列的名爲「GC Roots」的對象做爲起始點,從這些節點開始向下搜索,搜索所走過的路徑稱爲引用鏈(Reference Chain)。blog

            當一個對象到GC Roots沒有任何引用鏈相連時,則證實此對象是不可用的。內存

            在Java語言裏,可做爲GC Roots的對象包括下面幾種:資源

                虛擬機棧(棧幀中的本地變量表)中的引用的對象

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

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

                本地方法棧中JNI(即通常說的Native方法)的引用的對象

    何時回收?

            當內存消耗完或者是達到某一個閥值(Threshold,使用內存佔總內存的比列)時,觸發垃圾回收操做。閥值可經過JVM參數配置。

    如何回收?

    GC機制的基本算法是 分代收集,

    當新生代的Eden區滿的時候,執行Minor GC,也叫 Young GC。使用了複製算法。

    當老年代內存不足時,將執行Major GC,也叫 Full GC。使用了標記-清除算法 或 標記-整理算法。

 

在GC機制中,起重要做用的是垃圾收集器,垃圾收集器是GC的具體實現。以下圖,

  

新生代收集器:(都是使用 中止複製算法

  • Serial收集器:使用中止複製算法,使用一個線程進行GC,串行,其它工做線程暫停。使用-XX:+UseSerialGC可使用Serial+Serial Old模式運行進行內存回收(這也是虛擬機在Client模式下運行的默認值)
  • ParNew收集器:使用中止複製算法,Serial收集器的多線程版,用多個線程進行GC,並行,其它工做線程暫停,關注縮短垃圾收集時間。使用-XX:+UseParNewGC開關來控制使用ParNew+Serial Old收集器組合收集內存;使用-XX:ParallelGCThreads來設置執行內存回收的線程數。
  • Parallel Scavenge 收集器:使用中止複製算法,關注CPU吞吐量。即運行用戶代碼的時間/總時間,好比:JVM運行100分鐘,其中運行用戶代碼99分鐘,垃 圾收集1分鐘,則吞吐量是99%,這種收集器能最高效率的利用CPU適合運行後臺運算(關注縮短垃圾收集時間的收集器,如CMS,等待時間不多,因此適 合用戶交互,提升用戶體驗)。使用-XX:+UseParallelGC開關控制使用Parallel Scavenge+Serial Old收集器組合回收垃圾(這也是在Server模式下的默認值);使用-XX:GCTimeRatio來設置用戶執行時間佔總時間的比例,默認99,即1%的時間用來進行垃圾回收。使用-XX:MaxGCPauseMillis設置GC的最大停頓時間(這個參數只對Parallel Scavenge有效),用開關參數-XX:+UseAdaptiveSizePolicy能夠進行動態控制,如自動調整Eden/Survivor比例,老年代對象年齡,新生代大小等,這個參數在ParNew下沒有。

老年代收集器:

    • Serial Old收集器:單線程收集器,串行,使用標記整理(整理的方法是Sweep(清理)和Compact(壓縮),清理是將廢棄的對象幹掉,只留倖存的對象,壓縮是將移動對象,將空間填滿保證內存分爲2塊,一塊全是對象,一塊空閒)算法,使用單線程進行GC,其它工做線程暫停(注意,在老年代中進行標記整理算法清理,也須要暫停其它線程),在JDK1.5以前,Serial Old收集器與ParallelScavenge搭配使用。
    • Parallel Old收集器:老年代收集器,多線程,並行,多線程機制與Parallel Scavenge差不錯,使用標記整理(與Serial Old不一樣,這裏的整理是Summary(彙總)和Compact(壓縮),彙總的意思就是將倖存的對象複製到預先準備好的區域,而不是像Sweep(清理)那樣清理廢棄的對象)算法,在Parallel Old執行時,仍然須要暫停其它線程。Parallel Old在多核計算中頗有用。Parallel Old出現後(JDK 1.6),與Parallel Scavenge配合有很好的效果,充分體現Parallel Scavenge收集器吞吐量優先的效果。使用-XX:+UseParallelOldGC開關控制使用Parallel Scavenge +Parallel Old組合收集器進行收集。
    • CMS(Concurrent Mark Sweep)收集器:老年代收集器,致力於獲取最短回收停頓時間(即縮短垃圾回收的時間),使用標記清除算法,多線程,優勢是併發收集用戶線程能夠和GC線程同時工做),停頓小。使用-XX:+UseConcMarkSweepGC進行ParNew+CMS+Serial Old進行內存回收,優先使用ParNew+CMS(緣由見後面),當用戶線程內存不足時,採用備用方案Serial Old收集。

 

G1收集器:在JDK1.7中正式發佈,與現狀的新生代、老年代概念有很大不一樣,目前使用較少,不作介紹。

相關文章
相關標籤/搜索