垃圾收集器及GC調優

垃圾收集器及GC調優

串行回收器

新生代串行回收器

特點

它僅僅使用單線程進行垃圾回收
它是獨佔式的垃圾回收
進行垃圾回收時, Java應用程序中的線程都需要暫停(Stop-The-World)
使用複製算法
適合CPU等硬件不是很好的場合
設置參數

-XX:+UseSerialGC 指定新生使用新生代串行收集器和老年代串行收集器, 當以client模式運行時, 它是默認的垃圾收集器

老年代串行回收器

特點

同新生代串行回收器一樣, 單線程, 獨佔式的垃圾回收器
通常老年代垃圾回收比新生代回收要更長時間, 所以可能會使應用程序停頓較長時間
設置參數

-XX:+UseSerialGC 新生代, 老年代都使用串行回收器
-XX:+UseParNewGC 新生代使用ParNew回收器, 老年代使用串行回收器
-XX:+UseParallelGC 新生代使用ParallelGC回收器, 老年代使用串行回收器

並行回收器

新生代ParNew回收器

特點

將串行回收多線程化
使用複製算法
垃圾回收時, 應用程序仍會暫停, 只不過由於是多線程回收, 在多核CPU上,回收效率會高於串行回收器, 反之在單核CPU, 效率會不如串行回收器
設置參數

-XX:+UseParNewGC 新生代使用ParNew回收器, 老年代使用串行回收器
-XX:+UseConcMarkSweepGC 新生代使用ParNew回收器, 老年代使用CMS回收器
-XX:ParallelGCThreads=n 指回ParNew回收器工作時的線程數量, cpu核數小時8時, 其值等於cpu數量, 高於8時,可以使用公式(3+((5*CPU_count)/8))

新生代ParallelGC回收器

特點

同ParNew回收器一樣, 不同的地方在於,它非常關注系統的吞吐量(通過參數控制)
使用複製算法
支持自適應的GC調節策略
設置參數

-XX:+UseParallelGC  新生代用ParallelGC回收器, 老年代使用串行回收器
-XX:+UseParallelOldGC  新生代用ParallelGC回收器, 老年代使用ParallelOldGC回收器系統吞吐量的控制:
-XX:MaxGCPauseMillis=n(單位ms)   設置垃圾回收的最大停頓時間,
-XX:GCTimeRatio=n(n在0-100之間)  設置吞吐量的大小, 假設值爲n, 那系統將花費不超過1/(n+1)的時間用於垃圾回收
-XX:+UseAdaptiveSizePolicy  打開自適應GC策略, 在這種模式下, 新生代的大小, eden,survivior的比例, 晉升老年代的對象年齡等參數會被自動調整,以達到堆大小, 吞吐量, 停頓時間之間的平衡點

老年代ParallelOldGC回收器

特點

同新生代的ParallelGC回收器一樣, 是屬於老年代的關注吞吐量的多線程併發回收器
使用標記壓縮算法
設置參數

-XX:+UseParallelOldGC  新生代用ParallelGC回收器, 老年代使用ParallelOldGC回收器, 是非常關注系統吞吐量的回收器組合, 適合用於對吞吐量要求較高的系統
-XX:ParallelGCThreads=n   指回ParNew回收器工作時的線程數量, cpu核數小時8時, 其值等於cpu數量, 高於8時, 可以使用公式(3+((5*CPU_count)/8))

CMS回收器(Concurrent Mark Sweep,併發標記清除)

老年代的併發回收器

特點

是併發回收, 非獨佔式的回收器, 大部分時候應用程序不會停止運行
針對年老代的回收器
使用併發標記清除算法, 因此回收後會有內存碎片, 可以使參數設置進行內存碎片的壓縮整理
與ParallelGC和ParallelOldGC不同, CMS主要關注系統停頓時間
主要步驟

初始標記
併發標記
預清理
重新標記
併發清理
併發重置
注:初始標記與重新標記是獨佔系統資源的,不能與用戶線程一起執行,而其它階段則可以與用戶線程一起執行

設置參數

-XX:-CMSPrecleaningEnabled  關閉預清理, 不進行預清理, 默認在併發標記後, 會有一個預清理的操作,可減少停頓時間
-XX:+UseConcMarkSweepGC  老年代使用CMS回收器, 新生代使用ParNew回收器
-XX:ConcGCThreads=n  設置併發線程數量,
-XX:ParallelCMSThreads=n  同上, 設置併發線程數量,
-XX:CMSInitiatingOccupancyFraction=n  指定老年代回收閥值, 即當老年代內存使用率達到這個值時, 會執行一次CMS回收,默認值爲68, 設置技巧: (Xmx-Xmn)*(100-CMSInitiatingOccupancyFraction)/100)>=Xmn
-XX:+UseCMSCompactAtFullCollection  開啓內存碎片的整理, 即當CMS垃圾回收完成後, 進行一次內存碎片整理, 要注意內存碎片的整理並不是併發進行的, 因此可能會引起程序停頓
-XX:CMSFullGCsBeforeCompation=n  用於指定進行多少次CMS回收後, 再進行一次內存壓縮
-XX:+CMSParallelRemarkEnabled  在使用UseParNewGC 的情況下, 儘量減少 mark 的時間
-XX:+UseCMSInitiatingOccupancyOnly  表示只有達到閥值時才進行CMS回收
-XX:+CMSConcurrentMTEnabled 當該標誌被啓用時,併發的CMS階段將以多線程執行,默認開啓
-XX:+CMSIncrementalMode 在增量模式下,CMS 收集器在併發階段,不會獨佔整個週期,
而會週期性的暫停,喚醒應用線程。收集器把併發階段工作,劃分爲片段,安排在次級(minor) 回收之間運行。這對需要低延遲,運行在少量CPU服務器上的應用很有用。

Class的回收(永久區的回收)

設置參數

-XX:+CMSClassUnloadingEnabled  開啓回收Perm區的內存, 默認情況下, 是需要觸發一次FullGC
-XX:CMSInitiatingPermOccupancyFraction=n  當永久區佔用率達到這個n值時,啓動CMS回收, 需上一個參數開啓的情況下使用

G1回收器(jdk1.7後全新的回收器, 用於取代CMS)

概述

特點

獨特的垃圾回收策略, 屬於分代垃圾回收器
使用分區算法, 不要求eden, 年輕代或老年代的空間都連續
並行性: 回收期間, 可由多個線程同時工作, 有效利用多核cpu資源
併發性: 與應用程序可交替執行, 部分工作可以和應用程序同時執行
分代GC: 分代收集器, 同時兼顧年輕代和老年代
空間整理: 回收過程中, 會進行適當對象移動, 減少空間碎片
可預見性: G1可選取部分區域進行回收, 可以縮小回收範圍, 減少全局停頓
主要步驟

1.新生代GC
2.併發標記週期

初始標記新生代GC(此時是並行, 應用程序會暫停止)–>根區域掃描–>併發標記–>重新標記(此時是並行, 應用程序會暫停止)–>獨佔清理(此時應用程序會暫停止)–>併發清理
3.混合回收

這個階段即會執行正常的年輕代gc, 也會選取一些被標記的老年代區域進行回收, 同時處理新生代和年老輕
若需要, 會進行FullGC

4.混合GC時發生空間不足

在新生代GC時, survivor區和老年代無法容納倖存對象時
以上兩者都會導致一次FullGC產生

設置參數

-XX:+UseG1GC  打開G1收集器開關,
-XX:MaxGCPauseMillis=n  指定目標的最大停頓時間,任何一次停頓時間超過這個值, G1就會嘗試調整新生代和老年代的比例, 調整堆大小, 調整晉升年齡
-XX:ParallelGCThreads=n  用於設置並行回收時, GC的工作線程數量
-XX:InitiatingHeapOccpancyPercent=n  指定整個堆的使用率達到多少時, 執行一次併發標記週期, 默認45, 過大會導致併發標記週期遲遲不能啓動, 增加FullGC的可能, 過小會導致GC頻繁, 會導致應用程序性能有所下降

參數選項

選項 默認值 描述
-XX:+UseG1GC 默認關閉 使用G1垃圾處理器
-XX:MaxGCPauseMillis=n 默認值:4294967295 設置並行收集最大暫停時間,這是一個理想目標,JVM將盡最大努力來實現它。
-XX:InitiatingHeapOccupancyPercent=n 默認值:45 啓動一個併發垃圾收集週期所需要達到的整堆佔用比例。這個比例是指整個堆的佔用比例而不是某一個代(例如G1),如果這個值是0則代表‘持續做GC’。默認值是45
-XX:NewRatio=n 默認值:2 設置年輕代和年老代的比值。例如:值爲3,則表示年輕代與年老代比值爲1:3,年輕代佔整個年輕代年老代和的1/4。
-XX:SurvivorRatio=n 默認值:8 年輕代中Eden區與兩個Survivor區的比值。注意Survivor區有兩個。如:3,表示Eden:Survivor=3:2,一個Survivor區佔整個年輕代的1/5
-XX:MaxTenuringThreshold=n 默認值:15 設置垃圾最大存活閥值。如果設置爲0的話,則年輕代對象不經過Survivor區,直接進入年老代。對於年老代比較多的應用,可以提高效率。如果將此值設置爲一個較大值,則年輕代對象會在Survivor區進行多次複製,這樣可以增加對象再年輕代的存活時間,增加在年輕代即被回收的概論。
-XX:ParallelGCThreads=n 默認值:隨JVM運行平臺不同而異 配置並行收集器的線程數,即:同時多少個線程一起進行垃圾回收。此值最好配置與處理器數目相等。
-XX:ConcGCThreads=n 默認值:隨JVM運行平臺不同而異 並行垃圾收集時,使用的線程數。默認值和JVM運行的平臺有關。
-XX:G1ReservePercent=n 默認值:10 設置保留用來做假天花板以減少晉升(新生代對象晉升到老生代)失敗可能性的堆數目。
-XX:G1HeapRegionSize=n 默認值根據堆大小而定 使用G1垃圾回收器,java堆被劃分成統一大小的區塊。這個選項設置每個區塊的大小。最小值是1Mb,最大值是32Mb。

其他GC相關的設置

System.gc()

(1)禁用System.gc()
  -XX:+DisableExplicitGC  禁止程序中調用System.gc(), 加了此參數, 程序若有調用, 返回的空函數調用
   System.gc()的調用, 會使用FullGC的方式回收整個堆而會忽略CMS或G1等相關回收器
(2)System.gc()使用併發回收
  -XX:+ExplicitGCCinvokesConcurrent   使用併發方式處理顯示的gc, 即開啓後, System.gc()這種顯示GC纔會併發的回收, (CMS, G1)

並行GC前額外觸發的新生代GC

(1)使用並行回收器(UseParallelGC或者UseParallelOldGC)時, 會額外先觸發一個新生代GC, 目的是儘可能減少停頓時間
(2)若不需要這種特性, 可以使用以下參數去除
  -XX:-ScavengeBeforeFullGC   即去除在FullGC之前的那次新生代GC, 原本默認值爲true

對象何時進入老年代

(1)當對象首次創建時, 會放在新生代的eden區, 若沒有GC的介入,會一直在eden區, GC後,是可能進入survivor區或者年老代
(2)當對象年齡達到一定的大小 ,就會離開年輕代, 進入老年代, 對象進入老年代的事件稱爲晉升, 而對象的年齡是由GC的次數決定的, 每一次GC,若對象沒有被回收, 則對象的年齡就會加1, 可以使用以下參數來控制新生代對象的最大年齡:
  -XX:MaxTenuringThreshold=n  假設值爲n , 則新生代的對象最多經歷n次GC, 就能晉升到老年代, 但這個必不是晉升的必要條件
  -XX:TargetSurvivorRatio=n  用於設置Survivor區的目標使用率,即當survivor區GC後使用率超過這個值, 就可能會使用較小的年齡作爲晉升年齡
(3)除年齡外, 對象體積也會影響對象的晉升的, 若對象體積太大, 新生代無法容納這個對象, 則這個對象可能就會直接晉升至老年代, 可通過以下參數使用對象直接晉升至老年代的閾值, 單位是byte
  -XX:PretenureSizeThreshold  即對象的大小大於此值, 就會繞過新生代, 直接在老年代分配, 此參數只對串行回收器以及ParNew回收有效, 而對ParallelGC回收器無效

在TLAB上分配對象(Thread Local Allocation Buffer, 線程本地分配緩存)

(1)TLAB: TLAB是一個線程專用的內存分配區域, 虛擬機爲線程分配空間, 針對於體積不大的對象, 會優先使用TLAB, 這個可以加速對象的分配, TLAB是默認開啓的, 若要關閉可以使用以下參數關閉
  -XX:-UseTLAB  關閉TLAB
  -XX:+UseTLAB  開啓TLAB, 默認也是開啓的
  -XX:+PrintTLAB  觀察TALB的使用情況
  -XX:TLABRefillWasteFraction=n  設置一個比率n, 而refill_waste的值就是(TLAB_SIZE/n), 即TLAB空間較小, 大對象無法分配在TLAB,所以會直接分配到堆上,TLAB較小也很容易裝滿, 因此當TLAB的空間不夠分配一個新對象, 就會考慮廢棄當前TLAB空間還是直接分配到堆上, 就會使用此參數進行判斷, 小於refill_waste就允許廢棄, 而新建TLAB來分配對象,而大於refill_waste就直接在堆上分配, 默認是64
  -XX:+ResizeTLAB  開啓TLAB自動調整大小, 默認是開啓的, 若要關閉把+號換成-號即可
  -XX:TLABSize=n  設置一個TLAB的大小, 前提先關閉TLAB的自動調整

其他參考

JVM7、8GC詳解 
JVM調優,選擇合適的收集器 

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