Java虛擬機--垃圾收集

Java虛擬機

1. JVM運行時數據區域

  • 參考書籍:《深刻理解Java虛擬機:JVM高級特性與最佳實踐,第二版》
  • 資料參考:http://blog.csdn.net/nms312/article/details/37361121
    imagejava

    2. 垃圾收集及內存分配

  • GC須要考慮的三個問題:
    1. 哪些內存須要回收?
    2. 何時回收?
    3. 怎麼回收?
  • JVM中主要討論堆和方法區裏的內存回收。 爲了解決上面三個問題:
    1. 哪些內存須要回收?即如何肯定須要回收的對象
      1. 引用計數算法
        • 主流的java虛擬機裏都沒有采用這種方法,由於它很難解決對象直接循環引用的問題。
      2. 可達性分析算法
        • 當一個對象到GC Roots沒有任何引用鏈時,則證實對象是不可用的。
        • 在JDK1.2以後,java將引用分爲強引用(Strong Reference),軟引用(Soft Reference),弱引用(weak Reference),虛引用(Phantom Reference)。
        • 在JVM中可達性分析算法要判斷一個對象須要回收,至少要通過兩次標記過程:
          • 若是對象在進行可達性分析後發現沒有與GC Roots的引用鏈,那它將會被第一次標記並進行一次篩選,篩選條件是是否有必要執行finalize()方法。當對象沒有覆蓋該方法,或者finalize()方法已經被虛擬機調用過,虛擬機將這兩種狀況都視爲「沒有必要執行」。
          • 若是判斷有必要執行,加入F-Queue隊列中。finalize()方法是對象逃脫被GC的最後一次機會,稍後GC將對隊列中的對象進行第二次標記,若是仍是沒法與GC roots創建關聯,將被真正回收。
    2. 怎麼回收?即垃圾收集算法
      • 標記-清除算法
        • 最基礎的收集算法,它主要有兩個不足:一個是效率問題,另外一個是空間問題,產生碎片太多。
      • 複製算法
        • 它將可用內存按容量劃分爲大小相等的兩塊, 每次只使用其中的一塊
        • 如今商業虛擬機都採用這種收集算法來回收新生代。
        • HotSpot虛擬機默認Eden和Survivor的大小比例是8:1
      • 標記-整理算法
        • 複製收集算法在對象存活率較高時就要進行較多的複製操做, 效率將會變低。因此在老年代裏通常不直接使用這種算法。
        • 標記過程仍然與「標記-清除」算法同樣, 但後續步驟不是直接對可回收對象進行清理, 而是讓全部存活的對象都向一端移動, 而後直接清理掉端邊界之外的內存。
      • 分代收集算法
        • 當前商業虛擬機的垃圾收集都採用「分代收集」( Generational Collection) 算法。根據對象存活週期的不一樣將內存劃分爲幾塊。 通常是把Java堆分爲新生代和老年代, 這樣就能夠根據各個年代的特色採用最適當的收集算法。

3. JDK的HotSpot虛擬機的垃圾收集器

  • 這裏討論的收集器基於JDK 1.7 Update 14以後的HotSpot虛擬機
    image
  • 展現了7種做用於不一樣分代的收集器,若是兩個收集器之間存在連線, 就說明它們能夠搭配使用。 虛擬機所處的區域, 則表示它是屬於新生代收集器仍是老年代收集器。
  • Serial收集器
    • Serial收集器是最基本,發展歷史最悠久的收集器,曾經(再JDK1.3以前)是虛擬機新生代收集的惟一選擇。
    • 它是一個單線程收集器,它在進行垃圾收集時,必須暫停其餘全部的工做線程,直到收集結束。
    • 它是虛擬機運行在client模式下的默認新生代收集器。
    • 優於其餘收集器的地方: 簡單而高效( 與其餘收集器的單線程比) , 對於限定單個CPU的環境來講, Serial收集器因爲沒有線程交互的開銷, 專心作垃圾收集天然能夠得到最高的單線程收集效率。
  • ParNew收集器
    • ParNew收集器其實就是Serial收集器的多線程版本。
    • ParNew收集器除了多線程收集以外, 其餘與Serial收集器相比並無太多創新之處, 但它倒是許多運行在Server模式下的虛擬機中首選的新生代收集器, 其中有一個與性能無關但很重要的緣由是, 除了Serial收集器外, 目前只有它能與CMS收集器配合工做。
    • 併發和並行:這兩個名詞都是併發編程中的概念
      • 並行( Parallel) : 指多條垃圾收集線程並行工做, 但此時用戶線程仍然處於等待狀態。
      • 併發( Concurrent) : 指用戶線程與垃圾收集線程同時執行( 但不必定是並行的, 可能會交替執行) , 用戶程序在繼續運行, 而垃圾收集程序運行於另外一個CPU上。
  • Parallel Scavenge收集器
    • Parallel Scavenge收集器是一個新生代收集器, 它也是使用複製算法的收集器, 又是並行的多線程收集器。
    • Parallel Scavenge收集器的目標是達到一個可控制的吞吐量( Throughput)。
    • 吞吐量=運行用戶代碼時間/( 運行用戶代碼時間+垃圾收集時間)
    • 因爲與吞吐量關係密切, Parallel Scavenge收集器也常常稱爲「吞吐量優先」收集器。
    • 自適應調節策略也是ParallelScavenge收集器與ParNew收集器的一個重要區
      別。
  • Serial Old收集器
    • Serial Old是Serial收集器的老年代版本, 它一樣是一個單線程收集器, 使用「標記-整理」算法。
    • 這個收集器的主要意義也是在於給Client模式下的虛擬機使用。
    • 在Server模式下, 那麼它主要還有兩大用途:
      • 一種用途是在JDK 1.5以及以前的版本中與Parallel Scavenge收集器搭配使用
      • 另外一種用途就是做爲CMS收集器的後備預案
  • Parallel Old收集器
    • Parallel Old是Parallel Scavenge收集器的老年代版本, 使用多線程和「標記-整理」算法。
    • 這個收集器是在JDK 1.6中才開始提供的, 在此以前, 新生代的Parallel Scavenge收集器一直處於比較尷尬的狀態。 緣由是, 若是新生代選擇了ParallelScavenge收集器, 老年代除了Serial Old( PS MarkSweep) 收集器外別無選擇
    • 直到Parallel Old收集器出現後, 「吞吐量優先」收集器終於有了比較名副其實的應用組合,在注重吞吐量以及CPU資源敏感的場合, 均可以優先考慮Parallel Scavenge加Parallel Old收集器。
  • CMS收集器
    • 在JDK 1.5時期,HotSpot推出了一款在強交互應用中幾乎可認爲有劃時代意義的垃圾收集器——CMS收集器( Concurrent Mark Sweep)
    • 這款收集器是HotSpot虛擬機中第一款真正意義上的併發( Concurrent) 收集器, 它第一次實現了讓垃圾收集線程與用戶線程( 基本上) 同時工做
    • CMS( Concurrent Mark Sweep)收集器是一種以獲取最短回收停頓時間爲目標的收集器。基於「標記—清除」算法實現,整個過程分爲4個步驟:
      • 初始標記( CMS initial mark)
      • 併發標記( CMS concurrent mark)
      • 從新標記( CMS remark)
      • 併發清除( CMS concurrent sweep)
    • 優勢:併發收集、 低停頓
    • 缺點:
      • CMS收集器對CPU資源很是敏感。
      • CMS收集器沒法處理浮動垃圾,可能出現「Concurrent Mode Failure」失敗而致使另外一次Full GC的產生。
      • CMS是一款基於「標記—清除」算法實現的收集器。意味着收集結束時會有大量空間碎片產生。
  • G1收集器
    • G1( Garbage-First) 收集器是當今收集器技術發展的最前沿成果之一,被視爲JDK 1.7中HotSpot虛擬機的一個重要進化特徵。
    • 特色:並行與併發,分代收集,空間整合,可預測的停頓。
    • 與CMS的「標記—清理」算法不一樣, G1從總體來看是基於「標記—整理」算法實現的收集器, 從局部( 兩個Region之間) 上來看是基於「複製」算法實現的, 但不管如何, 這兩種算法都意味着G1運做期間不會產生內存空間碎片,收集後能提供規整的可用內存。
相關文章
相關標籤/搜索