JVM垃圾回收機制算法總結

本文系轉載,原文地址:http://blog.csdn.net/willfcareer/archive/2010/08/23/5833082.aspx

Java虛擬機垃圾收集器分析

1 、活動對象

l  追蹤 root 對象算法: 深度追蹤 root 對象,將 heap 中所有被引用到的 root 做標誌,所有未被標誌的對象視爲非活動對象,所佔用的空間視爲非活動內存。

2 、常用算法

l  Copy 算法

1  方法:將內存分爲兩個區域( from space  to space )。所有的對象分配內存都分配到 from space 。在清理非活動對象階段,把所有標誌爲活動的對象, copy  to space ,之後清楚 from space 空間。然後互換 from sapce  to space 的身份。既原先的 from space 變成 to sapce ,原先的 to space 變成 from space 。每次清理,重複上述過程。

2  優點: copy 算法不理會非活動對象, copy 數量僅僅取決爲活動對象的數量。並且在 copy 的同時,整理了 heap 空間,即, to space 的空間使用始終是連續的,內存使用效率得到提高。

3  缺點:劃分 from space  to space ,內存的使用率是 1  2 。一般在 Young Generation 中使用。

l  Compaction 算法

1  方法:在清理非活動對象階段,刪除非活動對象佔用內存,並且把活動對象向 heap 的底部移動,直到所有的活動對象被移到 heap 的一側。

2  優點:無須劃分 from sapce  to space ,提高內存的使用率。並且 compaction 後的內存空間也是連續分配的。

3  缺點:該算法相對比較複雜。一般在 Tenured Generation 中使用

 

1、  內存劃分

l  Young Generation

1  生命週期很短的對象,歸爲 young generation 。由於生命週期很短,這部分對象在 gc 的時候,很大部分的對象已經成爲非活動對象。因此針對 young  generation 的對象,採用 copy 算法,只需要將少量的存活下來的對象 copy  to space 。存活的對象數量越少,那麼 copy 算法的效率越高。

2  young generation  gc 稱爲 minor gc 。經過數次 minor gc ,依舊存活的對象,將被移出 young generation ,移到 tenured generation

3  young generation 分爲:

1  eden :每當對象創建的時候,總是被分配在這個區域

2  survivor1  copy 算法中的 from space

3  survivor2  copy 算法中的 to sapce (備註:其中 survivor1  survivor2 的身份在每次 minor gc 後被互換)

4  minor gc 的時候,會把 eden+survivor1(2) 的對象 copy  survivor2(1) 去。

l  Tenured Generation

1  生命週期較長的對象,歸入到 tenured generation 。一般是經過多次 minor gc ,還 依舊存活的對象,將移入到 tenured generation 。(當然,在 minor gc 中如果存活的對象的超過 survivor 的容量,放不下的對象會直接移入到 tenured generation 

2  tenured generation  gc 稱爲 major gc ,就是通常說的 full gc 

3  採用 compactiion 算法。由於 tenured generaion 區域比較大,而且通常對象生命週期都比較常, compaction 需要一定時間。所以這部分的 gc 時間比較長。

4  minor gc 可能引發 full gc 。當 eden  from space 的空間大於 tenured generation 區的剩餘空間時,會引發 full gc 。這是悲觀算法,要確保 eden  from space 的對象如果都存活,必須有足夠的 tenured generation 空間存放這些對象。

l  Permanet Generation

1  該區域比較穩定,主要用於存放 classloader 信息,比如類信息和 method 信息。

                    2 對於 spring hibernate 這些需要動態類型支持的框架,這個區域需要足夠的空間。

算法補充:

基本回收算法

  1. 引用計數(Reference Counting)
    比較古老的回收算法。原理是此對象有一個引用,即增加一個計數,刪除一個引用則減少一個計數。垃圾回收時,只用收集計數爲0的對象。此算法最致命的是無法處理循環引用的問題。
  2. 標記-清除(Mark-Sweep)
    此算法執行分兩階段。第一階段從引用根節點開始標記所有被引用的對象,第二階段遍歷整個堆,把未標記的對象清除。此算法需要暫停整個應用,同時,會產生內存碎片。
  3. 複製(Copying)
    此算法把內存空間劃爲兩個相等的區域,每次只使用其中一個區域。垃圾回收時,遍歷當前使用區域,把正在使用中的對象複製到另外 一個區域中。次算法每次只處理正在使用中的對象,因此複製成本比較小,同時複製過去以後還能進行相應的內存整理,不過出現“碎片”問題。當然,此算法的缺 點也是很明顯的,就是需要兩倍內存空間。
  4. 標記-整理(Mark-Compact)
    此算法結合了“標記-清除”和“複製”兩個算法的優點。也是分兩階段,第一階段從根節點開始標記所有被引用對象,第二階段遍歷 整個堆,把清除未標記對象並且把存活對象“壓縮”到堆的其中一塊,按順序排放。此算法避免了“標記-清除”的碎片問題,同時也避免了“複製”算法的空間問 題。
  5. 增量收集(Incremental Collecting) 
    實施垃圾回收算法,即:在應用進行的同時進行垃圾回收。不知道什麼原因JDK5.0中的收集器沒有使用這種算法的。
  6. 分代(Generational Collecting)
    基於對對象生命週期分析後得出的垃圾回收算法。把對象分爲年青代、年老代、持久代,對不同生命週期的對象使用不同的算法(上述方式中的一個)進行回收。現在的垃圾回收器(從J2SE1.2開始)都是使用此算法的。

二、垃圾回收器


目前的收集器主要有三種:串行收集器、並行收集器、併發收集器 。

  1. 串行收集器 

    使用單線程處理所有垃圾回收工作,因爲無需多線程交互,所以效率比較高。但是,也無法使用多處理器的優勢,所以此收集器適合單處理器機器。當然,此收集器也可以用在小數據量(100M 左右)情況下的多處理器機器上。可以使用-XX:+UseSerialGC 打開。
  2. 並行收集器
    1. 對年輕代進行並行垃圾回收,因此可以減少垃圾回收時間。一般在多線程多處理器機器上使用。使用-XX:+UseParallelGC .打開。並行收集器在J2SE5.0第六6更新上引入,在Java SE6.0中進行了增強--可以堆年老代進行並行收集。如果年老代不使用併發收集的話,是使用單線程進行垃圾回收 ,因此會制約擴展能力。使用-XX:+UseParallelOldGC 打開。
    2. 使用-XX:ParallelGCThreads=<N> 設置並行垃圾回收的線程數。此值可以設置與機器處理器數量相等 。
    3. 此收集器可以進行如下配置:
      • 最大垃圾回收暫停: 指定垃圾回收時的最長暫停時間,通過-XX:MaxGCPauseMillis=<N> 指定。<N>爲毫秒.如果指定了此值的話,堆大小和垃圾回收相關參數會進行調整以達到指定值 。設定此值可能會減少應用的吞吐量。
      • 吞吐量: 吞吐量爲垃圾回收時間與非垃圾回收時間的比值 ,通過-XX:GCTimeRatio=<N> 來設定,公式爲1/(1+N) 。例如,-XX:GCTimeRatio=19時,表示5%的時間用於垃圾回收。默認情況爲99,即1%的時間用於垃圾回收。
  3. 併發收集器
    可以保證大部分工作都併發進行(應用不停止),垃圾回收只暫停很少的時間,此收集器適合對響應時間要求比較高的中、大規模應用。使用-XX:+UseConcMarkSweepGC 打開。
    1. 併發收集器主要減少年老代的暫停時間,他在應用不停止的情況下使用獨立的垃圾回收線程,跟蹤可達對象。在每個年老代垃圾回收週期 中,在收集初期併發收集器會對整個應用進行簡短的暫停,在收集中還會再暫停一次。第二次暫停會比第一次稍長,在此過程中多個線程同時進行垃圾回收工作。
    2. 併發收集器使用處理器換來短暫的停頓時間 。在一個N個處理器的系統上,併發收集部分使用K/N 個可用處理器進行回收,一般情況下1<=K<=N/4 。
    3. 在只有一個處理器的主機上使用併發收集器 ,設置爲incremental mode 模式也可獲得較短的停頓時間。
    4. 浮動垃圾 :由於在應用運行的同時進行垃圾回收,所以有些垃圾可能在垃圾回收進行完成時產生,這樣就造成了“Floating Garbage”,這些垃圾需要在下次垃圾回收週期時才能回收掉。所以,併發收集器一般需要20% 的預留空間用於這些浮動垃圾。
    5. Concurrent Mode Failure :併發收集器在應用運行時進行收集,所以需要保證堆在垃圾回收的這段時間有足夠的空間供程序使用,否則,垃圾回收還未完成,堆空間先滿了。這種情況下將會發生“併發模式失敗”,此時整個應用將會暫停,進行垃圾回收。
    6. 啓動併發收集器 :因爲併發收集在應用運行時進行收集,所以必須保證收集完成之前有足夠的內存空間供程序使用,否則會出現“Concurrent Mode Failure”。通過設置-XX:CMSInitiatingOccupancyFraction=<N> 指定還有多少剩餘堆時開始執行併發收集
  4. 小結
    • 串行處理器: 
      --適用情況:數據量比較小(100M左右);單處理器下並且對響應時間無要求的應用。
      --缺點:只能用於小型應用
    • 並行處理器: 
      --適用情況:“對吞吐量有高要求”,多CPU、對應用響應時間無要求的中、大型應用。舉例:後臺處理、科學計算。
      --缺點:應用響應時間可能較長
    • 併發處理器:
      --適用情況:“對響應時間有高要求”,多CPU、對應用響應時間有較高要求的中、大型應用。舉例:Web服務器/應用服務器、電信交換、集成開發環境。

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