1. 程式人生 > >第五章 JVM垃圾收集器(1)

第五章 JVM垃圾收集器(1)

說明:垃圾回收演算法是理論,垃圾收集器是回收演算法的實現,關於回收演算法,見《第四章 JVM垃圾回收演算法

1、七種垃圾收集器

  • Serial(序列GC)-- 複製
  • ParNew(並行GC)-- 複製
  • Parallel Scavenge(並行回收GC)-- 複製
  • Serial Old(MSC)(序列GC)-- 標記-整理
  • CMS(併發GC)-- 標記-清除
  • Parallel Old(並行GC)--標記-整理
  • G1(JDK1.7update14才可以正式商用)

說明:

  • 1~3用於年輕代垃圾回收:年輕代的垃圾回收稱為minor GC
  • 4~6用於年老代垃圾回收(當然也可以用於方法區的回收
    ):年老代的垃圾回收稱為full GC
  • G1獨立完成"分代垃圾回收"

注意:並行與併發

  • 並行:多條垃圾回收執行緒同時操作
  • 併發:垃圾回收執行緒與使用者執行緒一起操作

2、常用五種組合

  • Serial/Serial Old
  • ParNew/Serial Old:與上邊相比,只是比年輕代多了多執行緒垃圾回收而已
  • ParNew/CMS:當下比較高效的組合
  • Parallel Scavenge/Parallel Old:自動管理的組合
  • G1:最先進的收集器,但是需要JDK1.7update14以上

2.1、Serial/Serial Old:

特點:

  • 年輕代Serial收集器採用單個GC執行緒實現"複製"演算法(包括掃描、複製)
  • 年老代Serial Old收集器採用單個GC執行緒實現"標記-整理"演算法
  • Serial與Serial Old都會暫停所有使用者執行緒(即STW)

說明:

  • STW(stop the world):編譯程式碼時為每一個方法注入safepoint(方法中迴圈結束的點、方法執行結束的點),在暫停應用時,需要等待所有的使用者執行緒進入safepoint,之後暫停所有執行緒,然後進行垃圾回收。

適用場合:

  • CPU核數<2,實體記憶體<2G的機器(簡單來講,單CPU,新生代空間較小且對STW時間要求不高的情況下使用)
  • -XX:UseSerialGC:強制使用該GC組合
  • -XX:PrintGCApplicationStoppedTime:檢視STW時間

2.2、ParNew/Serial Old:

說明:

  • ParNew除了採用多GC執行緒來實現複製演算法以外,其他都與Serial一樣,但是此組合中的Serial Old又是一個單GC執行緒,所以該組合是一個比較尷尬的組合,在單CPU情況下沒有Serial/Serial Old速度快(因為ParNew多執行緒需要切換),在多CPU情況下又沒有之後的三種組合快(因為Serial Old是單GC執行緒),所以使用其實不多。
  • -XX:ParallelGCThreads:指定ParNew GC執行緒的數量,預設與CPU核數相同,該引數在於CMS GC組合時,也可能會用到

2.3、Parallel Scavenge/Parallel Old:

特點:

  • 年輕代Parallel Scavenge收集器採用多個GC執行緒實現"複製"演算法(包括掃描、複製)
  • 年老代Parallel Old收集器採用多個GC執行緒實現"標記-整理"演算法
  • Parallel Scavenge與Parallel Old都會暫停所有使用者執行緒(即STW)

說明:

  •  吞吐量:CPU執行程式碼時間/(CPU執行程式碼時間+GC時間)
  • CMS主要注重STW的縮短(該時間越短,使用者體驗越好,所以主要用於處理很多的互動任務的情況)
  • Parallel Scavenge/Parallel Old主要注重吞吐量(吞吐量越大,說明CPU利用率越高,所以主要用於處理很多的CPU計算任務而使用者互動任務較少的情況

引數設定:

  • -XX:+UseParallelOldGC:使用該GC組合
  • -XX:GCTimeRatio:直接設定吞吐量大小,假設設為19,則允許的最大GC時間佔總時間的1/(1+19),預設值為99,即1/(1+99)
  • -XX:MaxGCPauseMillis:最大GC停頓時間,該引數並非越小越好
  • -XX:+UseAdaptiveSizePolicy:開啟該引數,-Xmn/-XX:SurvivorRatio/-XX:PretenureSizeThreshold這些引數就不起作用了,虛擬機器會自動收集監控資訊,動態調整這些引數以提供最合適的的停頓時間或者最大的吞吐量(GC自適應調節策略),而我們需要設定的就是-Xmx,-XX:+UseParallelOldGC或-XX:GCTimeRatio兩個引數就好(當然-Xms也指定上與-Xmx相同就好)

注意:

  • -XX:GCTimeRatio和-XX:MaxGCPauseMillis設定一個就好
  • 不開啟-XX:+UseAdaptiveSizePolicy,-Xmn/-XX:SurvivorRatio/-XX:PretenureSizeThreshold這些引數依舊可以配置,以resin伺服器為例
                <jvm-arg>-Xms2048m</jvm-arg>
                <jvm-arg>-Xmx2048m</jvm-arg>
                <jvm-arg>-Xmn512m</jvm-arg>
                <jvm-arg>-Xss1m</jvm-arg>
                <jvm-arg>-XX:PermSize=256M</jvm-arg>
                <jvm-arg>-XX:MaxPermSize=256M</jvm-arg>
                <jvm-arg>-XX:SurvivorRatio=8</jvm-arg>
                <jvm-arg>-XX:MaxTenuringThreshold=15</jvm-arg>
    
                <jvm-arg>-XX:+UseParallelOldGC</jvm-arg>
                <jvm-arg>-XX:GCTimeRatio=19</jvm-arg>
    
                <jvm-arg>-XX:+PrintGCDetails</jvm-arg>
                <jvm-arg>-XX:+PrintGCTimeStamps</jvm-arg>
    View Code

適用場合:

  • 很多的CPU計算任務而使用者互動任務較少的情況
  • 不想自己去過多的關注GC引數,想讓虛擬機器自己進行調優工作

2.4、ParNew/CMS

說明:

  • 以上只是年老代CMS收集的過程,年輕代ParNew看"2.2、ParNew/Serial Old"就好
  • CMS是多回收執行緒的,不要被上圖誤導,預設的執行緒數:(CPU數量+3)/4
  • CMS主要注重STW的縮短(該時間越短,使用者體驗越好,所以主要用於處理很多的互動任務的情況)

特點:

  • 年輕代ParNew收集器採用多個GC執行緒實現"複製"演算法(包括掃描、複製)
  • 年老代CMS收集器採用多執行緒實現"標記-清除"演算法
    • 初始標記:標記與根集合節點直接關聯的節點。時間非常短,需要STW
    • 併發標記:遍歷之前標記到的關聯節點,繼續向下標記所有存活節點。時間較長。
    • 重新標記:重新遍歷trace併發期間修改過的引用關係物件。時間介於初始標記與併發標記之間,通常不會很長。需要STW
    • 併發清理:直接清除非存活物件,清理之後,將該執行緒佔用的CPU切換給使用者執行緒
  • 初始標記與重新標記都會暫停所有使用者執行緒(即STW),但是時間較短;併發標記與併發清理時間較長,但是不需要STW

關於併發標記期間怎樣記錄發生變動的引用關係物件,在重新標記期間怎樣掃描這些物件,見《第六章 JVM垃圾收集器(2)

缺點:

  • 併發標記與併發清理:按照說明的第二點來講,假設有2個CPU,那麼其中有一個CPU會用於垃圾回收,而另一個用於使用者執行緒,這樣的話,之前是兩CPU執行使用者執行緒,現在是一個,那麼效率就會急劇下降。也就是說,降低了吞吐量(即降低了CPU使用率)。
  • 併發清理:在這一過程中,產生的垃圾無法被清理(因為發生在重新標記之後)
  • 併發標記與併發清理:由於是與使用者執行緒併發的,所以使用者執行緒可能會分配物件,這樣既可能物件直接進入年老代(例如,大物件),也可能進入年輕代後,年輕代發生minor GC,這樣的話,實際上要求我們的年老代需要預留一定空間,也就是說要在年老代還有一定空間的情況下就要進行垃圾回收,留出一定記憶體空間來供其他執行緒使用,而不能等到年老代快爆滿了才進行垃圾回收,通過-XX:CMSInitiatingOccupancyFraction來指定當年老代空間滿了多少後進行垃圾回收,如果在回收過程中,老年代已經不夠使用了,這時候CMS回收失敗,老年代使用serial Old進行GC
  • 標記-清理演算法:會產生記憶體碎片,由於是在老年代,可能會提前觸發Full GC(這正是我們要儘量減少的)

引數設定:

  • -XX:+UseConcMarkSweepGC:使用該GC組合
  • -XX:CMSInitiatingOccupancyFraction:指定當年老代空間滿了多少後進行垃圾回收
  • -XX:+UseCMSCompactAtFullCollection:(預設是開啟的)在CMS收集器頂不住要進行FullGC時開啟記憶體碎片整理過程,該過程需要STW
  • -XX:CMSFullGCsBeforeCompaction:指定多少次FullGC後才進行整理
  • -XX:ParallelCMSThreads:指定CMS回收執行緒的數量,預設為:(CPU數量+3)/4

適用場合:

  • 用於處理很多的互動任務的情況
  • 方法區的回收一般使用CMS,配置兩個引數:-XX:+CMSPermGenSweepingEnabled與-XX:+CMSClassUnloadingEnabled

3、一些經驗

  • 由於當下大型企業用的比較多的還是jdk1.6版本,所以G1用的還是不多
  • 用得最多的兩種:ParNew/CMS和Parallel Scavenge/Parallel Old
  • Full GC的四種情況
    • 舊生代空間不足
      • 不要建立過大的物件獲陣列
      • 儘量讓物件在minor GC被回收
      • 讓物件在年輕代多存活一段時間,可能這段時間內就會被minor GC回收
    • 方法區滿了
      • 增大方法區
      • 使用CMS GC回收方法區
    • CMS GC中promotion failed(minor GC時,survivor區放不下,年老區也放不下)和concurrent mode failure
      • 增大survivor區
      • 增大年老區
      • 調低-XX:CMSInitiatingOccupancyFraction
      • 設定:-XX:CMSMaxAbortablePrecleanTime=5(單位:ms),防止CMS在重新標記很久後才進行併發清理
    • 空間擔保機制(這一塊兒見《深入理解Java虛擬機器(第二版)》P98)

附:具體的配置引數檢視《深入理解Java虛擬機器(第二版)》P90

相關推薦

JVM垃圾收集1

說明:垃圾回收演算法是理論,垃圾收集器是回收演算法的實現,關於回收演算法,見《第四章 JVM垃圾回收演算法》 1、七種垃圾收集器 Serial(序列GC)-- 複製 ParNew(並行GC)-- 複製 Parallel Scavenge(並行回收GC)-- 複製 Serial Old(MSC)(

JVM垃圾收集2

1、G1 說明: 從上圖來看,G1與CMS相比,僅在最後的"篩選回收"部分不同(CMS是併發清除),實際上G1回收器的整個堆記憶體的劃分都與其他收集器不同。 CMS需要配合ParNew,G1可單獨回收整個空間 原理: G1收集器將整個堆劃分為多個大小相等的Region G1

JVM垃圾收集1

ads vivo 計算 square 算法 round 兩種 多線程 lin 此文已由作者趙計剛薪授權網易雲社區發布。歡迎訪問網易雲社區,了解更多網易技術產品運營經驗。說明:垃圾回收算法是理論,垃圾收集器是回收算法的實現,關於回收算法,見《第四章 JVM垃圾回收算法》1、七

JVM垃圾收集 —— 老年代垃圾收集

上一篇文章講了新生代的垃圾收集器,這篇文章我們來講講老年代的垃圾收集器 Serial Old收集器 1、說明:一個單執行緒收集器,使用“標記-整理”演算法。其實就是Serial收集器老年代的版本 2、優缺點 和 執行圖 和Serial收集器一樣,所以這裡就不多贅

JVM垃圾收集 —— 概念:新生代和老年代、並行和併發

在上篇文章中我們講到了垃圾回收的幾種演算法。垃圾收集演算法是記憶體回收的方法論,而垃圾收集器是垃圾回收的具體實現。 在瞭解垃圾收集器之前,本篇文章先來簡單的說一下新生代和老年代、並行和併發的概念。 新生代和老年代 從記憶體回收的角度來看,一般我們可以將Java堆分

JVM - 垃圾收集

HotSpot虛擬機器垃圾收集器的種類以及作用空間(連線表示兩個收集器可以搭配使用) Serial 收集器:該收集器單執行緒工作,在gc時暫停使用者其他所有的工作執行緒即“Stop The World”,新生代採用複製演算法,老年代採用 標記-整理 演算法,是虛擬機器執行在Client模式

JVM垃圾收集2

此文已由作者趙計剛薪授權網易雲社群釋出。 歡迎訪問網易雲社群,瞭解更多網易技術產品運營經驗。 1、G1 說明: 從上圖來看,G1與CMS相比,僅在最後的"篩選回收"部分不同(CMS是併發清除),實際上G1回收器的整個堆記憶體的劃分都與其他收集器不同。 CMS需要配合Pa

JVM垃圾收集 —— 預設的垃圾收集

在前面的幾篇文章講述了各種垃圾收集器,但是問題來了,我們在Linux或者Windows安裝的 jdk 預設是什麼收集器呢? 開啟控制檯,在控制檯中輸入一下命令: java -XX:+PrintCommandLineFlags -version 32位的windo

深入理解JVM垃圾收集與記憶體分配策略

概述 對於Java記憶體執行時區域的各位部分,其中程式計數器、虛擬機器棧、本地方法棧這三個區域都是隨執行緒而生,隨執行緒而滅。並且棧幀中分配的記憶體也是在編譯後就已知的。因此這幾個區域的記憶體分配和回收都具備確定性,所以我們在這幾個區域就不必過多地考慮

詳解JVM垃圾收集演算法&垃圾收集圖解

垃圾收集演算法:記憶體回收的方法論 垃圾收集器:記憶體回收的具體實現 在正式討論垃圾回收演算法和垃圾收集器之前,我們應該瞭解一下JVM是如何判斷一個物件已經死亡的? JVM主要使用了兩種方法判斷物件是否已經死亡:

JVM初窺:垃圾收集

參考書籍:《深入理解Java虛擬機器——JVM高階特性與最佳實踐(第2版)》 Java語言出來之前,程式開發更多的是使用C或者C++語言,然而在C或者C++語言中存在一個很大的矛盾:建立物件時要不斷

:循環結構

如何 如何使用 滿足 為什麽 發現 每日 生活 打印機 結構 第五章:循環結構(一) 1.什麽是循環結構 在日常生活中,會有很多需要反復執行的事情,比如:每一年的 4個季節,每一周的7天,每日的3餐,打印機每份文檔打印50 份,一圈跑道400米跑3圈,都是在反復執行的。 2

MNIST數字識別問題

AR dom post mod 變量名 elements 之前 spl with 4.1. ckpt文件保存方法 在對模型進行加載時候,需要定義出與原來的計算圖結構完全相同的計算圖,然後才能進行加載,並且不需要對定義出來的計算圖進行初始化操作。 這樣保存下來的模型,會在其文

《C++ Primer Plus》學習筆記—— 迴圈和關係表示式

本章內容: for迴圈和while迴圈 表示式和語句 運算子組合 複合語句 逗號運算子以及關係運算符 typedef工具 字元輸入方法get() 檔案尾條件 巢狀迴圈和二維陣列 計算機除了儲存資料外,還可以做很多其他工作。可以對資料進

6 征服CSS3選擇

屬性選擇器 在HTML中,通過各種各樣的屬性可以給元素增加很多附加的資訊。例如,通過id屬性可以將不同div元素進行區分。 在CSS2中引入了一些屬性選擇器,而CSS3在CSS2的基礎上對屬性選擇器進行了擴充套件,新增了3個屬性選擇器,使得屬性選擇器有了萬用字元的概念,這三個屬性選擇器與CSS2的屬性選擇器

7 征服CSS3選擇

:enabled選擇器 在Web的表單中,有些表單元素有可用(“:enabled”)和不可用(“:disabled”)狀態,比如輸入框,密碼框,複選框等。在預設情況之下,這些表單元素都處在可用狀態。那麼我們可以通過偽選擇器“:enabled”對這些表單元素設定樣式。 示例演示 通過“:enabled”選擇器

《C++ Primer Plus》學習筆記—— 迴圈和關係表示式

while迴圈 while迴圈是沒有初始化和更新部分的for迴圈,它只有測試條件和迴圈體。 while (test-condition) { body; } //當test-condition為true,即不為0時,執行迴圈體。 編寫延時迴圈 long wai

《C++ Primer Plus》學習筆記—— 迴圈和關係表示式

迴圈與文字輸入 迴圈完成的一項最常見最重要的任務:逐字元地讀取來自檔案或鍵盤的文字。 cin物件支援三種不同模式的單字元輸入,其使用者介面各不相同。 使用原始的cin進行輸入: 通過迴圈來讀取鍵盤的文字輸入,則必須有辦法停止讀取。 一種方法是選擇某個特殊的字元(哨兵

《C++ Primer Plus》學習筆記—— 迴圈和關係表示式

程式設計練習 1.編寫一個要求使用者輸入兩個整數的程式。該程式將計算並輸出這兩個整數之間(包括這兩個整數)所有整數的和。這裡假設先輸入較小的整數。例如,如果使用者輸入的是2和9,則程式將指出2~9之間的所有整數的和為44. #include <iostream>

卷積神經網路CNN

第五章 卷積神經網路(CNN) 標籤(空格分隔): 深度學習 5.1 卷積神經網路的組成層 在卷積神經網路中,有3種最主要的層: 卷積運算層 池化層 全連線層 一個完整的神經網路就是由這三種層疊加組成的。 結構