JVM系列三(垃圾收集器).

1、概述

1. 哪些內存須要回收

上篇文章 咱們介紹了 Java 內存運行時區域的各個部分,其中程序計數器、虛擬機棧、本地方法棧三個區域隨線程而生,隨線程而滅,在這幾個區域內就不須要過多考慮回收的問題,由於方法結束或者線程結束時,內存天然就跟着回收了。html

而方法區和 Java 堆是線程共享的,咱們只有在程序處於運行期間才能知道會建立哪些對象,這部份內存的分配和回收都是動態的,垃圾收集器所關注的是這部份內存。java

2. 回收方法區

方法區的垃圾收集主要回收兩部份內容:廢棄常量和無用的類。算法

「廢棄常量」指的是當前系統中沒有任何一個對象引用指向該常量。多線程

「無用的類」須要同時知足下面三個條件纔有可能被虛擬機回收,至於最終是否回收還由虛擬機參數:-Xnoclassgc 控制。併發

  • 該類的全部實例都已被回收,也就是 Java 堆中不存在該類的任何實例。
  • 加載該類的 ClassLoader 已經被回收。
  • 該類對應的 Class 對象沒有被任何地方被引用,沒法在任何地方經過反射訪問該類的接口。

2、垃圾回收器

首先開始以前先看下 HotSpot 虛擬機所包含的收集器:

圖中展現了7種做用於不一樣分代的收集器,若是兩個收集器之間存在連線,則說明它們能夠搭配使用。虛擬機所處的區域則表示它是屬於新生代仍是老年代收集器。jvm

1. Serial 收集器

新生代收集器,複製算法收集,Serial 收集器是最基本、發展歷史最悠久的收集器。它是一個單線程的收集器,只會使用一個 CPU 或一條收集線程去完成垃圾收集工做,它在垃圾收集時,必須暫停其餘全部的工做線程,直到它收集結束。
優化

優勢:簡單高效;虛擬機 Client 模式下表現優異(Client 模式下內存較小、CPU較少,能減小許多線程交互的開銷)。
缺點:回收工做須要 Stop The World ;單線程;不適用虛擬機 Server 模式(Server 模式下內存較大、CPU較多,致使回收工做停頓時間過長)。ui

2. ParNew 收集器

新生代收集器,複製算法收集,ParNew 收集器其實就是 Serial 收集器的多線程版本,除了使用多線程進行回收外,其他行爲包括控制參數、收集算法、Stop The World、對象分配規則、回收策略等都與 Serial 收集器徹底同樣。
線程

優勢:多線程工做;能夠與 CMS 收集器搭配工做;虛擬機 Server 模式下表現優異。
缺點:回收工做須要 Stop The World 。htm

3. Parallel Scavenge 收集器

新生代收集器,複製算法收集,多線程工做,Parallel Scavenge 收集器的關注點在於達到一個可控制的吞吐量(其餘收集器的關注點是縮短垃圾收集時用戶線程的停頓時間),停頓時間越短越適合須要與用戶交互的程序;而高吞吐量則能夠高效率的利用 CPU 時間,儘快完成程序的運行任務。

GC 自適應調節策略是 Parallel Scavenge 收集器和 ParNew 收集器的一個重要區別。它變現爲:只須要把基本的內存數據設置好(如 -Xmx 設置最大堆),而後使用 MaxGCPauseMillis 參數(更關注最大停頓時間)或 GCRatio(更關注吞吐量)給虛擬機設立一個優化目標,那具體細節參數的調節工做就由虛擬機來完成了。

優勢:多線程工做;注重系統吞吐量和CPU資源;自適應調節策略。
缺點:回收工做須要 Stop The World ;可選的老年代收集器過少,沒法與 CMS 收集器配合工做,在 JDK1.5 以前只能和 Serial Old 收集器配合工做。

tips:

  • 吞吐量 = 運行用戶代碼時間 / (運行用戶代碼時間 + 垃圾收集時間)
  • 自適應調節策略使用 -XX:+UseAdptiveSizePolicy 參數打開。
  • 與吞吐量關係密切,故也稱爲「吞吐量優先」收集器。

4. Serial Old 收集器

老年代收集器,標記-整理算法,單線程,Serial Old 收集器是 Serial 收集器的老年代版本。

優勢:虛擬機 Client 模式下表現尚可(Client 模式下內存較小、CPU較少,能減小許多線程交互的開銷);CMS 收集器的後備預案(在併發收集Concurent Mode Failure時使用)。
缺點:回收工做須要 Stop The World ;單線程。

5. Parallel Old 收集器

老年代收集器,標記-整理算法,多線程,Parallel Old 收集器是 Parallel Scavenge 收集器的老年代版本,在 JDK1.6 後開始提供。

優勢:搭配 Parallel Scavenge 收集器使用,關注系統吞吐量以及CPU資源。
缺點:回收工做須要 Stop The World ;可搭配的新生代收集器僅有 Parallel Scavenge 收集器而已。

6. CMS 收集器

老年代收集器,標記-清除算法,多線程,CMS(Concurrent Mark Sweep)收集器是一種以得到最短回收停頓時間爲目標的收集器,是真正意義上與用戶線程併發運行的收集器,所以,使用 CMS 收集器能給用戶帶來良好的體驗。

優勢:併發收集;低停頓。
缺點:

  1. CMS 收集器對 CPU 資源敏感,在併發標記/清理 的時候,雖然不會致使用戶線程停頓,但標記/清理工做是要佔用一部分 CPU 資源的,這無疑會下降吞吐量。(CMS 默認啓動的回收線程數是 (CPU 數量 + 3)/ 4)
  2. CMS 收集器沒法處理浮動垃圾(Floating Garbage),可能出現 「Concurent Mode Failure」 失敗而致使另外一次 Full GC 的產生(使用 Serial Old 收集器)。浮動垃圾指的是併發清理階段,用戶線程併發運行產生的垃圾,當這些浮動垃圾的內存超過了CMS 運行期間預留的內存,就會致使 「Concurent Mode Failure」 失敗。
  3. CMS 收集器使用的標記-清除算法會有大量的內存碎片出現,將會給大對象分配帶來不少麻煩。

7. G1 收集器

分區(Region)收集器,標記-整理算法和複製算法,多線程,G1(Garbage-First)收集器在 JDK 7u4 版本發佈,在 JDK9 中成爲默認垃圾收集器,是一款面向服務端應用的垃圾收集器,它的目標也是得到最短停頓時間。

優勢:

  1. 並行和併發,縮短 Stop The World 停頓的時間。
  2. 標記-整理算法、複製算法不會出現相似 CMS 的內存碎片問題。
  3. 可預測的停頓時間模型,能讓使用者明確指定在一個長度爲 M 毫秒的時間片斷內,消耗在垃圾收集上的時間不超過 N 毫秒。

推薦場景:

G1的首要目的是爲那些須要大容量內存和較小 GC 延遲的應用程序提供解決方案。這一般是指那些堆大小設置在 6GB 以上,肯定的、能夠預測的暫停時間在 0.5 秒之內的應用程序。

若是應用程序符合如下一項或者多項特徵,那麼從 CMS 或者 ParallelOld 收集器切換到 G1 可能更合適。

  • 活動對象佔據了超過 50% 的 Java 堆空間。
  • 對象分配率或者提高率波動明顯。
  • 不但願有長時間的垃圾收集暫停時間(超過0.5秒或1秒)。



參考連接:

  1. 《深刻理解 JVM 虛擬機》
  2. G1垃圾收集器介紹
  3. jvm垃圾收集器(終結篇)
相關文章
相關標籤/搜索