
說明
針對jdk7
關于垃圾回收
可以檢視我之前的博文:
JVM記憶體管理-垃圾回收與記憶體配置設定
垃圾收集器分類
- 按線程數分
可以分為串行垃圾回收器和并行垃圾回收器。串行垃圾回收器一次隻使用一個線程進行垃圾回收;并行垃圾回收器一次将開啟多個線程同時進行垃圾回收。在并行能力較強的 CPU 上,使用并行垃圾回收器可以縮短 GC 的停頓時間。
- 按照工作模式分
可以分為并發式垃圾回收器和獨占式垃圾回收器。并發式垃圾回收器與應用程式線程交替工作,以盡可能減少應用程式的停頓時間;獨占式垃圾回收器 (Stop the world) 一旦運作,就停止應用程式中的其他所有線程,直到垃圾回收過程完全結束
- 按碎片處理方式
可分為壓縮式垃圾回收器和非壓縮式垃圾回收器。壓縮式垃圾回收器會在回收完成後,對存活對象進行壓縮整理,消除回收後的碎片;非壓縮式的垃圾回收器不進行這步操作。
- 按工作的記憶體區間
可分為新生代垃圾回收器和老年代垃圾回收器
垃圾收集器的名額
- 吞吐量
指在應用程式的生命周期内,應用程式所花費的時間和系統總運作時間的比值。系統總運作時間=應用程式耗時+GC 耗時。如果系統運作了 100min,GC 耗時 1min,那麼系統的吞吐量就是 (100-1)/100=99%。
垃圾回收器負載:和吞吐量相反,垃圾回收器負載指來記回收器耗時與系統運作總時間的比值。
- 停頓時間
指垃圾回收器正在運作時,應用程式的暫停時間。對于獨占回收器而言,停頓時間可能會比較長。使用并發的回收器時,由于垃圾回收器和應用程式交替運作,程式的停頓時間會變短,但是,由于其效率很可能不如獨占垃圾回收器,故系統的吞吐量可能會較低。
- 垃圾回收頻率
指垃圾回收器多長時間會運作一次。一般來說,對于固定的應用而言,垃圾回收器的頻率應該是越低越好。通常增大堆空間可以有效降低垃圾回收發生的頻率,但是可能會增加回收産生的停頓時間。
- 反應時間
指當一個對象被稱為垃圾後多長時間内,它所占據的記憶體空間會被釋放。
- 堆配置設定
不同的垃圾回收器對堆記憶體的配置設定方式可能是不同的。一個良好的垃圾收集器應該有一個合理的堆記憶體區間劃分。
垃圾收集器介紹
新生代串行收集器
串行收集器主要有兩個特點:第一,它僅僅使用單線程進行垃圾回收;第二,它獨占式的垃圾回收。
在串行收集器進行垃圾回收時,Java 應用程式中的線程都需要暫停,等待垃圾回收的完成,這樣給使用者體驗造成較差效果。雖然如此,串行收集器卻是一個成熟、經過長時間生産環境考驗的極為高效的收集器。新生代串行處理器使用複制算法,實作相對簡單,邏輯處理特别高效,且沒有線程切換的開銷。在諸如單 CPU 處理器或者較小的應用記憶體等硬體平台不是特别優越的場合,它的性能表現可以超過并行回收器和并發回收器。在 HotSpot 虛拟機中,使用-XX:+UseSerialGC 參數可以指定使用新生代串行收集器和老年代串行收集器。當 JVM 在 Client 模式下運作時,它是預設的垃圾收集器。
老年代串行收集器
老年代串行收集器使用的是标記-壓縮算法。和新生代串行收集器一樣,它也是一個串行的、獨占式的垃圾回收器。由于老年代垃圾回收通常會使用比新生代垃圾回收更長的時間,是以,在堆空間較大的應用程式中,一旦老年代串行收集器啟動,應用程式很可能會是以停頓幾秒甚至更長時間。雖然如此,老年代串行回收器可以和多種新生代回收器配合使用,同時它也可以作為 CMS 回收器的備用回收器。若要啟用老年代串行回收器,可以嘗試使用以下參數:-XX:+UseSerialGC: 新生代、老年代都使用串行回收器。
如果使用-XX:+UseParNewGC 參數設定,表示新生代使用并行收集器,老年代使用串行收集器
如果使用-XX:+UseParallelGC 參數設定,表示新生代和老年代均使用并行回收收集器
【聲明:轉載請注明出處
獨立:http://wangnan.tech
簡書:http://www.jianshu.com/u/244399b1d776
CSDN:http://blog.csdn.net/wangnan9279】
并行收集器
并行收集器是工作在新生代的垃圾收集器,它隻簡單地将串行回收器多線程化。它的回收政策、算法以及參數和串行回收器一樣。
并行回收器也是獨占式的回收器,在收集過程中,應用程式會全部暫停。但由于并行回收器使用多線程進行垃圾回收,是以,在并發能力比較強的 CPU 上,它産生的停頓時間要短于串行回收器,而在單 CPU 或者并發能力較弱的系統中,并行回收器的效果不會比串行回收器好,由于多線程的壓力,它的實際表現很可能比串行回收器差。
開啟并行回收器可以使用參數-XX:+UseParNewGC,該參數設定新生代使用并行收集器,老年代使用串行收集器。
設定參數-XX:+UseConcMarkSweepGC 可以要求新生代使用并行收集器,老年代使用 CMS。
并行收集器工作時的線程數量可以使用-XX:ParallelGCThreads 參數指定。一般,最好與 CPU 數量相當,避免過多的線程數影響垃圾收集性能
新生代并行回收 (Parallel Scavenge) 收集器
新生代并行回收收集器也是使用複制算法的收集器。從表面上看,它和并行收集器一樣都是多線程、獨占式的收集器。但是,并行回收收集器有一個重要的特點:它非常關注系統的吞吐量。
新生代并行回收收集器可以使用以下參數啟用:
-XX:+UseParallelGC:新生代使用并行回收收集器,老年代使用串行收集器。
-XX:+UseParallelOldGC:新生代和老年代都是用并行回收收集器。
新生代并行回收收集器可以使用以下參數啟用:
-XX:+MaxGCPauseMills:設定最大垃圾收集停頓時間,它的值是一個大于 0 的整數。收集器在工作時會調整 Java 堆大小或者其他一些參數,盡可能地把停頓時間控制在 MaxGCPauseMills 以内。如果希望減少停頓時間,而把這個值設定得很小,為了達到預期的停頓時間,JVM 可能會使用一個較小的堆 (一個小堆比一個大堆回收快),而這将導緻垃圾回收變得很頻繁,進而增加了垃圾回收總時間,降低了吞吐量。
-XX:+GCTimeRatio:設定吞吐量大小,它的值是一個 0-100 之間的整數。假設 GCTimeRatio 的值為 n,那麼系統将花費不超過 1/(1+n) 的時間用于垃圾收集。比如 GCTimeRatio 等于 19,則系統用于垃圾收集的時間不超過 1/(1+19)=5%。預設情況下,它的取值是 99,即不超過 1%的時間用于垃圾收集。
除此之外,并行回收收集器與并行收集器另一個不同之處在于,它支援一種自适應的 GC 調節政策,使用-XX:+UseAdaptiveSizePolicy 可以打開自适應 GC 政策。在這種模式下,新生代的大小、eden 和 survivor 的比例、晉升老年代的對象年齡等參數會被自動調整,以達到在堆大小、吞吐量和停頓時間之間的平衡點。在手工調優比較困難的場合,可以直接使用這種自适應的方式,僅指定虛拟機的最大堆、目标的吞吐量 (GCTimeRatio) 和停頓時間 (MaxGCPauseMills),讓虛拟機自己完成調優工作
老年代并行回收收集器
老年代的并行回收收集器也是一種多線程并發的收集器。和新生代并行回收收集器一樣,它也是一種關注吞吐量的收集器。老年代并行回收收集器使用标記-壓縮算法,JDK1.6 之後開始啟用。
使用-XX:+UseParallelOldGC 可以在新生代和老生代都使用并行回收收集器,這是一對非常關注吞吐量的垃圾收集器組合,在對吞吐量敏感的系統中,可以考慮使用。參數-XX:ParallelGCThreads 也可以用于設定垃圾回收時的線程數量。
CMS 收集器
與并行回收收集器不同,CMS 收集器主要關注于系統停頓時間。CMS 是 Concurrent Mark Sweep 的縮寫,意為并發标記清除,從名稱上可以得知,它使用的是标記-清除算法,同時它又是一個使用多線程并發回收的垃圾收集器。
CMS 工作時,主要步驟有:初始标記、并發标記、重新标記、并發清除和并發重置。其中初始标記和重新标記是獨占系統資源的,而并發标記、并發清除和并發重置是可以和使用者線程一起執行的。是以,從整體上來說,CMS 收集不是獨占式的,它可以在應用程式運作過程中進行垃圾回收。
根據标記-清除算法,初始标記、并發标記和重新标記都是為了标記出需要回收的對象。并發清理則是在标記完成後,正式回收垃圾對象;并發重置是指在垃圾回收完成後,重新初始化 CMS 資料結構和資料,為下一次垃圾回收做好準備。并發标記、并發清理和并發重置都是可以和應用程式線程一起執行的。
CMS 收集器在其主要的工作階段雖然沒有暴力地徹底暫停應用程式線程,但是由于它和應用程式線程并發執行,互相搶占 CPU,是以在 CMS 執行期内對應用程式吞吐量造成一定影響。CMS 預設啟動的線程數是 (ParallelGCThreads+3)/4),ParallelGCThreads 是新生代并行收集器的線程數,也可以通過-XX:ParallelCMSThreads 參數手工設定 CMS 的線程數量。當 CPU 資源比較緊張時,受到 CMS 收集器線程的影響,應用程式的性能在垃圾回收階段可能會非常糟糕。
由于 CMS 收集器不是獨占式的回收器,在 CMS 回收過程中,應用程式仍然在不停地工作。在應用程式工作過程中,又會不斷地産生垃圾。這些新生成的垃圾在目前 CMS 回收過程中是無法清除的。同時,因為應用程式沒有中斷,是以在 CMS 回收過程中,還應該確定應用程式有足夠的記憶體可用。是以,CMS 收集器不會等待堆記憶體飽和時才進行垃圾回收,而是目前堆記憶體使用率達到某一門檻值時,便開始進行回收,以確定應用程式在 CMS 工作過程中依然有足夠的空間支援應用程式運作。
這個回收門檻值可以使用-XX:CMSInitiatingOccupancyFraction 來指定,預設是 68。即當老年代的空間使用率達到 68%時,會執行一次 CMS 回收。如果應用程式的記憶體使用率增長很快,在 CMS 的執行過程中,已經出現了記憶體不足的情況,此時,CMS 回收将會失敗,JVM 将啟動老年代串行收集器進行垃圾回收。如果這樣,應用程式将完全中斷,直到垃圾收集完成,這時,應用程式的停頓時間可能很長。是以,根據應用程式的特點,可以對-XX:CMSInitiatingOccupancyFraction 進行調優。如果記憶體增長緩慢,則可以設定一個稍大的值,大的門檻值可以有效降低 CMS 的觸發頻率,減少老年代回收的次數可以較為明顯地改善應用程式性能。反之,如果應用程式記憶體使用率增長很快,則應該降低這個門檻值,以避免頻繁觸發老年代串行收集器。
标記-清除算法将會造成大量記憶體碎片,離散的可用空間無法配置設定較大的對象。在這種情況下,即使堆記憶體仍然有較大的剩餘空間,也可能會被迫進行一次垃圾回收,以換取一塊可用的連續記憶體,這種現象對系統性能是相當不利的,為了解決這個問題,CMS 收集器還提供了幾個用于記憶體壓縮整理的算法。
-XX:+UseCMSCompactAtFullCollection 參數可以使 CMS 在垃圾收集完成後,進行一次記憶體碎片整理。記憶體碎片的整理并不是并發進行的。-XX:CMSFullGCsBeforeCompaction 參數可以用于設定進行多少次 CMS 回收後,進行一次記憶體壓縮。
-XX:CMSInitiatingOccupancyFraction 設定為 100,同時設定-XX:+UseCMSCompactAtFullCollection 和-XX:CMSFullGCsBeforeCompaction,日志輸出如下:
關于CMS收集器,深入了解閱讀下面的博文
link
G1 收集器 (Garbage First)
G1 收集器的目标是作為一款伺服器的垃圾收集器,是以,它在吞吐量和停頓控制上,預期要優于 CMS 收集器。
與 CMS 收集器相比,G1 收集器是基于标記-壓縮算法的。是以,它不會産生空間碎片,也沒有必要在收集完成後,進行一次獨占式的碎片整理工作。G1 收集器還可以進行非常精确的停頓控制。它可以讓開發人員指定當停頓時長為 M 時,垃圾回收時間不超過 N。使用參數-XX:+UnlockExperimentalVMOptions –XX:+UseG1GC 來啟用 G1 回收器,設定 G1 回收器的目标停頓時間:-XX:MaxGCPauseMills=20,-XX:GCPauseIntervalMills=200。
關于G1收集器,深入了解閱讀下面的博文
link
link
GC 相關參數總結
-
與串行回收器相關的參數
-XX:+UseSerialGC:在新生代和老年代使用串行回收器。
-XX:+SurvivorRatio:設定 eden 區大小和 survivor 區大小的比例。
-XX:+PretenureSizeThreshold:設定大對象直接進入老年代的門檻值。當對象的大小超過這個值時,将直接在老年代配置設定。
-XX:MaxTenuringThreshold:設定對象進入老年代的年齡的最大值。每一次 Minor GC 後,對象年齡就加 1。任何大于這個年齡的對象,一定會進入老年代。
-
與并行 GC 相關的參數
-XX:+UseParNewGC: 在新生代使用并行收集器。
-XX:+UseParallelOldGC: 老年代使用并行回收收集器。
-XX:ParallelGCThreads:設定用于垃圾回收的線程數。通常情況下可以和 CPU 數量相等。但在 CPU 數量比較多的情況下,設定相對較小的數值也是合理的。
-XX:MaxGCPauseMills:設定最大垃圾收集停頓時間。它的值是一個大于 0 的整數。收集器在工作時,會調整 Java 堆大小或者其他一些參數,盡可能地把停頓時間控制在 MaxGCPauseMills 以内。
-XX:GCTimeRatio:設定吞吐量大小,它的值是一個 0-100 之間的整數。假設 GCTimeRatio 的值為 n,那麼系統将花費不超過 1/(1+n) 的時間用于垃圾收集。
-XX:+UseAdaptiveSizePolicy:打開自适應 GC 政策。在這種模式下,新生代的大小,eden 和 survivor 的比例、晉升老年代的對象年齡等參數會被自動調整,以達到在堆大小、吞吐量和停頓時間之間的平衡點。
-
與 CMS 回收器相關的參數
-XX:+UseConcMarkSweepGC: 新生代使用并行收集器,老年代使用 CMS+串行收集器。
-XX:+ParallelCMSThreads: 設定 CMS 的線程數量。
-XX:+CMSInitiatingOccupancyFraction:設定 CMS 收集器在老年代空間被使用多少後觸發,預設為 68%。
-XX:+UseFullGCsBeforeCompaction:設定進行多少次 CMS 垃圾回收後,進行一次記憶體壓縮。
-XX:+CMSClassUnloadingEnabled:允許對類中繼資料進行回收。
-XX:+CMSParallelRemarkEndable:啟用并行重标記。
-XX:CMSInitatingPermOccupancyFraction:當永久區占用率達到這一百分比後,啟動 CMS 回收 (前提是-XX:+CMSClassUnloadingEnabled 激活了)。
-XX:UseCMSInitatingOccupancyOnly:表示隻在到達門檻值的時候,才進行 CMS 回收。
-XX:+CMSIncrementalMode:使用增量模式,比較适合單 CPU。
-
與 G1 回收器相關的參數
-XX:+UseG1GC:使用 G1 回收器。
-XX:+UnlockExperimentalVMOptions:允許使用實驗性參數。
-XX:+MaxGCPauseMills:設定最大垃圾收集停頓時間。
-XX:+GCPauseIntervalMills:設定停頓間隔時間。
-
其他參數
-XX:+DisableExplicitGC: 禁用顯示 GC。
(本文完)
參考:
- https://www.ibm.com/developerworks/cn/java/j-lo-JVMGarbageCollection/
- https://github.com/pzxwhc/MineKnowContainer/issues/89
- https://github.com/pzxwhc/MineKnowContainer/issues/90
- http://ifeve.com/%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3g1%E5%9E%83%E5%9C%BE%E6%94%B6%E9%9B%86%E5%99%A8/
- http://chenchendefeng.iteye.com/blog/455883
- http://www.jianshu.com/p/50d5c88b272d