JAVA垃圾回收機制

在java中垃圾回收是系統自動完成的,瞭解它對優化應用程序有很大的幫助。那麼我們就從下面幾個方面來了解垃圾回收機制:

  1. 哪些對象需要回收?
  2. 什麼時候回收?
  3. 怎麼去回收?

判斷對象可以回收的方法:

引用計數算法

引用計數

給對象中添加一個引用計數器,每當有一個地方引用它時,計數器值就加1;當引用失效時,計數器值就減1;任何時刻計數器爲0的對象就是不可能再被使用的。

優點:簡單,高效,現在的objective-c用的就是這種算法。
缺點:很難處理循環引用,相互引用的兩個對象則無法釋放。

可達性分析算法(根搜索算法)

可達性分析
從GC Roots(每種具體實現對GC Roots有不同的定義)作爲起點,向下搜索它們引用的對象,可以生成一棵引用樹,樹的節點視爲可達對象,反之視爲不可達。
在Java語言中,可以作爲GC Roots的對象包括下面幾種:

  • 虛擬機棧(棧幀中的本地變量表)中的引用對象。
  • 方法區中的類靜態屬性引用的對象。
  • 方法區中的常量引用的對象。
  • 本地方法棧中JNI(Native方法)的引用對象

真正標記以爲對象爲可回收狀態至少要標記兩次。

常見概念介紹

引用類型分類

引用類型有四種類型分別是:強引用(Strong Reference)、軟引用(soft Reference)、弱引用(Weak Reference)、虛引用(Phantom Reference),其中強引用是我們常用到的。下面來說明下他們什麼時候會被垃圾回收機制回收。
強引用: 這種最頑強,只要有一個引用存在,永遠都不會被回收掉。
軟引用: 一般是指還有用,但是非必須的對象。在內存空間不足的情況下,會回收掉此部分內存,如果還不夠則會拋出內存溢出異常。
弱引用: 一般指非必須的對象,比軟引用還要弱,它只能生存到下一次垃圾回收前,如果一旦發生垃圾回收,它將會被回收掉。
虛引用: 最弱的引用關係,無法通過虛引用來取得一個對象的實例。爲一個對象設置虛引用的唯一目的就是能夠在這個對象被回收的時候收到一個系統通知。

併發與並行

  • 並行(Parallel): 指多條垃圾收集線程並行工作,但此時用戶線程仍然處於等待狀態。

  • 併發(Concurrent):指用戶線程與垃圾收集線程同時執行(但不一定是並行的,可能會交替執行),用戶程序在繼續運行,而垃圾收集程序運行於另一個CPU上。

Minor GC 和 Full GC

  • 新生代GC(Minor GC):指發生在新生代的垃圾收集動作,因爲Java對象大多都具備朝生夕滅的特性,所以Minor GC非常頻繁,一般回收速度也比較快。

  • 老年代GC(Major GC / Full GC):指發生在老年代的GC,出現了Major GC,經常會伴隨至少一次的Minor GC(但非絕對的,在Parallel Scavenge收集器的收集策略裏就有直接進行Major GC的策略選擇過程)。Major GC的速度一般會比Minor GC慢10倍以上。

吞吐量

吞吐量就是CPU用於運行用戶代碼的時間與CPU總消耗時間的比值,即吞吐量 = 運行用戶代碼時間 /(運行用戶代碼時間 + 垃圾收集時間)。
虛擬機總共運行了100分鐘,其中垃圾收集花掉1分鐘,那吞吐量就是99%。

Stop the world 概念

因爲垃圾回收的時候,需要整個的引用狀態保持不變,否則判定是判定垃圾,等我稍後回收的時候它又被引用了,這就全亂套了。所以,GC的時候,其他所有的程序執行處於暫停狀態,卡住了。
幸運的是,這個卡頓是非常短(尤其是新生代),對程序的影響微乎其微 (關於其他GC比如併發GC之類的,在此不討論)。
所以GC的卡頓問題由此而來,也是情有可原,暫時無可避免。

finalize需要注意地方
同一個對象的finalize 方法只會執行一次。
在給對象A賦值爲空後進行手動調用gc回收內存,會執行復寫了finalize方法,在finalize中再將A賦值一個非空的值,再次進行賦值爲空,調用gc,之後就不會再執行finalize方法了。

幾種垃圾回收算法

  1. 標記清除算法
  2. 複製算法算法
  3. 標記整理算法
  4. 分帶回收算法

標記清除算法

這個按名字就很容易理解,就是標記哪些是可回收的,然後進行清除回收處理。標記-清除算法分爲兩個階段:標記階段和清除階段,標記階段主要爲標記那些對象是可以回收的,清除就是回收標記過的那部分內存空間。
mark_clear

優點: 簡單,易實現
缺點: 容易產生內存碎片,對於後面分配大空間時,找不到足夠的空間,而主動會觸發一次內存回收,增加內存回收的次數。

複製算法

此方法將內存按容量分爲兩塊,例如A、B兩塊,每次只使用其中的一塊,當要進行回收操作時,將A中還存活的對象複製到B塊中(假設上次使用A),然後對A中所有對象清空就又構成一個完整的內存塊。這種方法就避免了標記清除的內存碎片問題。
copying

優點: 快速高效,不會產生內存碎片。
缺點: 可用內存會減少一半,因爲是按照均分的。

注意: 效率也與存活對象的多少有關,如果存活對象多,複製就多,效率就低了。

標記整理法

標記整理法就是在標記清除方法上進行的優化,主要是在標記完成後將這些存活的對象向一端移動,然後將末尾邊界後的所有內存空間清除。

java-gc-compact

優點: 適合存活對象多的,不產生內存碎片

分代回收法

分代回收算法實際上是把複製算法和標記整理法的結合,並不是真正一個新的算法,一般分爲:老年代(Old Generation)和新生代(Young Generation),老年代就是很少垃圾需要進行回收的,新生代就是有很多的內存空間需要回收,所以不同代就採用不同的回收算法,以此來達到高效的回收算法。
新生代:由於新生代產生很多臨時對象,大量對象需要進行回收,所以採用複製算法是最高效的。
老年代:回收的對象很少,都是經過幾次標記後都不是可回收的狀態轉移到老年代的,所以僅有少量對象需要回收,故採用標記清除或者標記整理算法。
所以以上整個過程就達到了最高效的回收辦法。

注意:新生代與老年代分配的比例爲 2:1

分代回收法詳解

分代算法主要核心思想是上面兩種算法的結合,但是它裏面還有一些特殊的地方,所以這裏進行特別的說明。
上面用到的複製算法,按照前面講的,按照空間1:1分配的,但是分代算法中不是這樣的,而是按照8:2 (4:1)的比例進行分配的,其中後面一塊又等分成了兩塊,也就是8:1:1的比例,8爲新生代(Eden區),1分別爲兩塊等大小的Survivor區。
所有新創建的對象都是放在Eden區的,所以有很多的臨時變量,故每次大部分回收的垃圾都是在Eden區的,所以Eden區會分配那麼多的空間,那爲什麼要分兩塊Survivor區呢? 是因爲,在進行一次coping算法回收時將Eden區中存活的對象複製到Survivor區,然後在進行一次回收時,Survivor區的存活對象沒地方存放了,因爲Eden區每次都有新創建的對象存在。故在新建一塊Survivor B區,這時將Eden和Survivor A區存活的對象放在B區,然後清空Eden和Survivor A區。這樣就相當於A和B每次回收後都有一個是全新的也就是空的,就是爲了循環這種操作。

分代回收,內存是如何分配的

  1. 新創建一個對象,默認是分在Eden區的,當Eden區內存不夠時,觸發一次minor gc (新生代回收),Eden區存活對象放入Survivor A區,然後新對象放入Eden區。
  2. 再新建一個對象,放入Eden區發現又滿了,在進行minor gc,這時將Eden區和Survivor A區存活的對象移動到Survivor B區,然後清空Eden和Survivor A。
  3. 如果再來一個新對象,Eden區又滿了,則再進行minor gc,移動到A區,然後清空Eden和B區,如果多次這樣,有些長久的對象就會在不斷的Survivor A和Survivor B區之間來回移動,多次之後,虛擬機默認15次後,就會將這些對象全部移動到老年區區。
  4. 如果新對象在eden區放不下,則直接放入老年代
  5. 如果Survivor 區放不下的對象,也直接放入老年代
  6. 發現老年代也滿了,則進行一次Full gc (major gc)

火車回收算法

垃圾收集算法一個很大的缺點就是難以控制垃圾回收所佔用的CPU時間,以及何時需要進行垃圾回收。火車算法是分代收集器所用的算法,目的是在成熟對象空間中提供限定時間的漸進收集。目前應用於SUN公司的Hotspot虛擬機上。
在火車算法中,內存被分爲塊,多個塊組成一個集合。爲了形象化,一節車廂代表一個塊,一列火車代表一個集合。
注意每個車廂大小相等,但每個火車包含的車廂數不一定相等。垃圾收集以車廂爲單位,收集順序按被創建的先後順序進行。

具體參考:http://blog.csdn.net/feier7501/article/details/21748615

常用垃圾回收機制

  1. 標記-清除收集器
    這種收集器首先遍歷對象圖並標記可到達的對象,然後掃描堆棧以尋找未標記對象並釋放它們的內存。這種收集器一般使用單線程工作並停止其他操作。
  2. 標記-壓縮收集器
    有時也叫標記-清除-壓縮收集器,與標記-清除收集器有相同的標記階段。在第二階段,則把標記對象複製到堆棧的新域中以便壓縮堆棧。這種收集器也停止其他操作。
  3. 複製收集器
    這種收集器將堆棧分爲兩個域,常稱爲半空間。每次僅使用一半的空間,虛擬機生成的新對象則放在另一半空間中。垃圾回收器運行時,它把可到達對象複製到另一半空間,沒有被複制的的對象都是不可達對象,可以被回收。這種方法適用於短生存期的對象,持續複製長生存期的對象由於多次拷貝,導致效率降低。缺點是隻有一半的虛擬機空間得到使用。
  4. 增量收集器
    增量收集器把堆棧分爲多個域,每次僅從一個域收集垃圾。這會造成較小的應用程序中斷。
  5. 分代收集器
    這種收集器把堆棧分爲兩個或多個域,用以存放不同壽命的對象。虛擬機生成的新對象一般放在其中的某個域中。過一段時間,繼續存在的對象將獲得使用期並轉入更長壽命的域中。分代收集器對不同的域使用不同的算法以優化性能。這樣可以減少複製對象的時間。
  6. 併發收集器
    併發收集器與應用程序同時運行。這些收集器在某點上(比如壓縮時)一般都不得不停止其他操作以完成特定的任務,但是因爲其他應用程序可進行其他的後臺操作,所以中斷其他處理的實際時間大大降低。
  7. 並行收集器
    並行收集器使用某種傳統的算法並使用多線程並行的執行它們的工作。在多CPU機器上使用多線程技術可以顯著的提高java應用程序的可擴展性。
  8. 自適應收集器
    根據程序運行狀況以及堆的使用狀況,自動選一種合適的垃圾回收算法。這樣可以不侷限與一種垃圾回收算法。

幾種垃圾收集器

常見的垃圾收集器有:serial收集器、Parallel收集器、Parallel Old 垃圾收集器、CMS(Concurrent Mark-Sweep)收集器、G1收集器.其中Serial收集器爲串行收集器,其他均爲並行收集器。

串行垃圾回收器(Serial Garbage Collector)
並行垃圾回收器(Parallel Garbage Collector)
併發標記掃描垃圾回收器(CMS Garbage Collector)
G1垃圾回收器(G1 Garbage Collector)

Serial收集器->串行收集器 (-XX:+UseSerialGC)

最古老,最穩定,簡單而高效,可能會產生較長的停頓。
Serial是一個單線程的收集器,它不僅僅只會使用一個CPU或一條線程去完成垃圾收集工作,並且在進行垃圾收集的同時,必須暫停其他所有的工作線程,直到垃圾收集結束。
Serial垃圾收集器雖然在收集垃圾過程中需要暫停所有其他的工作線程,但是它簡單高效,對於限定單個CPU環境來說,沒有線程交互的開銷,可以獲得最高的單線程垃圾收集效率,因此Serial垃圾收集器依然是java虛擬機運行在Client模式下默認的新生代垃圾收集器。

java-gc-serial

Serial Old收集器

Serial Old是Serial垃圾收集的老年代版本。它同樣是個單線程的收集器,使用標記-整理算法,這個收集器也主要是運行在Client默認的java虛擬機默認的年老代垃圾收集器。

ParNew收集器 (-XX:+UseParallelGC)

ParNew收集器其實就是Serial收集器的多線程版本,除了使用多條線程進行垃圾收集之外,其餘行爲包括Serial收集器可用的所有控制參數、收集算法、Stop The World、對象分配規則、回收策略等都與Serial收集器完全一樣,在實現上,這兩種收集器也共用了相當多的代碼。ParNew收集器是許多運行在Server模式下的虛擬機中首選的新生代收集器。
ParNew收集器

Parallel Scavenge

Parallel Scavenge是一個新生代收集器,使用多線程和複製算法。相比其他收集器,只有這個收集器是針對系統吞吐量進行改進,適用於後臺運算並且交互不多的程序。其他收集器則更關注改善收集時的停頓時間,適用於用戶交互的程序。

Parallel Old 垃圾收集器(-XX:+UseParallelOldGC)

Parallel Old是Parallel Scavenge收集器的老年代版本,使用多線程和“標記-整理”算法。
在注重吞吐量以及CPU資源敏感的場合,都可以優先考慮Parallel Scavenge加Parallel Old收集器。

Parallel

CMS 收集器

CMS(Concurrent Mark Sweep)收集器是一種以獲取最短回收停頓時間爲目標的收集器。目前很大一部分的Java應用集中在互聯網站或者B/S系統的服務端上,這類應用尤其重視服務的響應速度,希望系統停頓時間最短,以給用戶帶來較好的體驗。
CMS收集器是基於“標記—清除”算法實現的。整個過程需要下面四個步驟。

  1. 初始標記(CMS initial mark)
    初始標記僅僅只是標記一下GC Roots能直接關聯到的對象,速度很快,需要“Stop The World”。
  2. 併發標記(CMS concurrent mark)
    併發標記階段就是進行GC Roots Tracing的過程。
  3. 重新標記(CMS remark)
    重新標記階段是爲了修正併發標記期間因用戶程序繼續運作而導致標記產生變動的那一部分對象的標記記錄,這個階段的停頓時間一般會比初始標記階段稍長一些,但遠比並發標記的時間短,仍然需要“Stop The World”。
  4. 併發清除(CMS concurrent sweep)
    併發清除階段會清除對象。

優點: 併發收集、低停頓。
缺點:
CMS收集器對CPU資源非常敏感,以爲在併發階段佔用一部分線程(CPU資源),導致應用程序變慢,總吞吐量變低。CMS默認啓動的回收線程數是(CPU數量+3)/4,也就是當CPU在4個以上時,併發回收時垃圾收集線程不少於25%的CPU資源,並且隨着CPU數量的增加而下降。

CMS收集器無法處理浮動垃圾,可能出現“Concurrent Mode Failure”失敗而導致另一次Full GC的產生。
也是由於在垃圾收集階段用戶線程還需要運行,那也就還需要預留有足夠的內存空間給用戶線程使用,因此CMS收集器不能像其他收集器那樣等到老年代幾乎完全被填滿了再進行收集,需要預留一部分空間提供併發收集時的程序運作使用。要是CMS運行期間預留的內存無法滿足程序需要,就會出現一次“Concurrent Mode Failure”失敗,這時虛擬機將啓動後備預案:臨時啓用Serial Old收集器來重新進行老年代的垃圾收集,這樣停頓時間就很長了。

CMS是一款基於“標記—清除”算法實現的收集器,這意味着收集結束時會有大量空間碎片產生。空間碎片過多時,將會給大對象分配帶來很大麻煩,往往會出現老年代還有很大空間剩餘,但是無法找到足夠大的連續空間來分配當前對象,不得不提前觸發一次Full GC。

浮動垃圾: 由於CMS併發清理階段用戶線程還在運行着,伴隨程序運行自然就還會有新的垃圾不斷產生,這一部分垃圾出現在標記過程之後,CMS無法在當次收集中處理掉它們,只好留待下一次GC時再清理掉,本地無法清理的垃圾則稱爲浮動垃圾。

G1 收集器

G1收集器是當前收集器技術發展最前沿的成果,一款面向服務端應用的垃圾收集器。基於標記-整理算法,也就是說不會產生內存碎片,可以精確控制停頓。基本不犧牲吞吐量的前提下完成低停頓的內存回收。這是由於它將新生代、老年代劃分爲多個區域,並維護一個每個區域收集的優先列表,保證了在有限的時間內可以獲得最高的收集效率。收集的範圍是整個JAVA堆。而不是在區分新生代,老年代。

執行過程:

  1. 初始標記(Initial Marking)
    初始標記階段僅僅只是標記一下GC Roots能直接關聯到的對象,並且修改TAMS(Next Top at Mark Start)的值,讓下一階段用戶程序併發運行時,能在正確可用的Region中創建新對象,這階段需要停頓線程,但耗時很短。
  2. 併發標記(Concurrent Marking)
    併發標記階段是從GC Root開始對堆中對象進行可達性分析,找出存活的對象,這階段耗時較長,但可與用戶程序併發執行。
  3. 最終標記(Final Marking)
    最終標記階段是爲了修正在併發標記期間因用戶程序繼續運作而導致標記產生變動的那一部分標記記錄,虛擬機將這段時間對象變化記錄在線程Remembered Set Logs裏面,最終標記階段需要把Remembered Set Logs的數據合併到Remembered Set中,這階段需要停頓線程,但是可並行執行。
  4. 篩選回收(Live Data Counting and Evacuation)
    篩選回收階段首先對各個Region的回收價值和成本進行排序,根據用戶所期望的GC停頓時間來制定回收計劃,這個階段其實也可以做到與用戶程序一起併發執行,但是因爲只回收一部分Region,時間是用戶可控制的,而且停頓用戶線程將大幅提高收集效率。

特點:

  • 並行與併發
    可使用多個CPU來縮短Stop-The-World停頓的時間,部分其他收集器原本需要停頓Java線程執行的GC動作,G1收集器仍然可以通過併發的方式讓Java程序繼續執行。
  • 分代收集
    與其他收集器一樣,分代概念在G1中依然得以保留。雖然G1可以不需要其他收集器配合就能獨立管理整個GC堆,但它能夠採用不同的方式去處理新創建的對象和已經存活了一段時間、熬過多次GC的舊對象以獲取更好的收集效果。
  • 空間整合
    與CMS的“標記—清理”算法不同,G1從整體來看是基於“標記—整理”算法實現的收集器,從局部(兩個Region之間)上來看是基於“複製”算法實現的,但無論如何,這兩種算法都意味着G1運作期間不會產生內存空間碎片,收集後能提供規整的可用內存。這種特性有利於程序長時間運行,分配大對象時不會因爲無法找到連續內存空間而提前觸發下一次GC。
  • 可預測的停頓
    這是G1相對於CMS的另一大優勢,降低停頓時間是G1和CMS共同的關注點,但G1除了追求低停頓外,還能建立可預測的停頓時間模型,能讓使用者明確指定在一個長度爲M毫秒的時間片段內,消耗在垃圾收集上的時間不得超過N毫秒。

在G1之前的其他收集器進行收集的範圍都是整個新生代或者老年代,而G1不再是這樣。使用G1收集器時,Java堆的內存佈局就與其他收集器有很大差別,它將整個Java堆劃分爲多個大小相等的獨立區域(Region),雖然還保留有新生代和老年代的概念,但新生代和老年代不再是物理隔離的了,它們都是一部分Region(不需要連續)的集合。

G1收集器之所以能建立可預測的停頓時間模型,是因爲它可以有計劃地避免在整個Java堆中進行全區域的垃圾收集。G1跟蹤各個Region裏面的垃圾堆積的價值大小(回收所獲得的空間大小以及回收所需時間的經驗值),在後臺維護一個優先列表,每次根據允許的收集時間,優先回收價值最大的Region(這也就是Garbage-First名稱的來由)。這種使用Region劃分內存空間以及有優先級的區域回收方式,保證了G1收集器在有限的時間內可以獲取儘可能高的收集效率

幾種收集器對比

Serial收集器 VS ParNew收集器

ParNew收集器在單CPU的環境中絕對不會有比Serial收集器更好的效果,甚至由於存在線程交互的開銷,該收集器在通過超線程技術實現的兩個CPU的環境中都不能百分之百地保證可以超越Serial收集器。
然而,隨着可以使用的CPU的數量的增加,它對於GC時系統資源的有效利用還是很有好處的。

Parallel Scavenge收集器 VS CMS等收集器:

Parallel Scavenge收集器的特點是它的關注點與其他收集器不同,CMS等收集器的關注點是儘可能地縮短垃圾收集時用戶線程的停頓時間,而Parallel Scavenge收集器的目標則是達到一個可控制的吞吐量(Throughput)。
由於與吞吐量關係密切,Parallel Scavenge收集器也經常稱爲“吞吐量優先”收集器。

Parallel Scavenge收集器 VS ParNew收集器:

Parallel Scavenge收集器與ParNew收集器的一個重要區別是它具有自適應調節策略。

GC自適應的調節策略(GC Ergonomics):
Parallel Scavenge收集器有一個參數-XX:+UseAdaptiveSizePolicy。當這個參數打開之後,就不需要手工指定新生代的大小、Eden與Survivor區的比例、晉升老年代對象年齡等細節參數了,虛擬機會根據當前系統的運行情況收集性能監控信息,動態調整這些參數以提供最合適的停頓時間或者最大的吞吐量,這種調節方式稱爲GC自適應的調節策略(GC Ergonomics)。

觸發GC的類型

瞭解這些是爲了解決實際問題,Java虛擬機會把每次觸發GC的信息打印出來來幫助我們分析問題,所以掌握觸發GC的類型是分析日誌的基礎。

GC_FOR_MALLOC 表示是在堆上分配對象時內存不足觸發的GC。
GC_CONCURRENT 當我們應用程序的堆內存達到一定量,或者可以理解爲快要滿的時候,系統會自動觸發GC操作來釋放內存。
GC_EXPLICIT 表示是應用程序調用System.gc、VMRuntime.gc接口或者收到SIGUSR1信號時觸發的GC。
GC_BEFORE_OOM 表示是在準備拋OOM異常之前進行的最後努力而觸發的GC。

垃圾回收的JVM配置

運行的垃圾回收器類型

配置 描述
-XX:+UseSerialGC 串行垃圾回收器
-XX:+UseParallelGC 並行垃圾回收器
-XX:+UseConcMarkSweepGC 併發標記掃描垃圾回收器
-XX:ParallelCMSThreads= 併發標記掃描垃圾回收器,=爲使用的線程數量
-XX:+UseG1GC G1垃圾回收器

GC的優化配置

配置 描述
-Xms 初始化堆內存大小
-Xmx 堆內存最大值
-Xmn 新生代大小
-XX:PermSize 初始化永久代大小
-XX:MaxPermSize 永久代最大容量

使用JVM GC參數的例子

1
java -Xmx12m -Xms3m -Xmn1m -XX:PermSize=20m -XX:MaxPermSize=20m -XX:+UseSerialGC -jar java-application.jar

總結

內存回收與垃圾收集器在很多時候都是影響系統性能,併發能力的主要因素之一,虛擬機之所以提供多種不同的收集器及大量的參數調節,是因爲只有根據具體實際需要,實現方式選擇最優的收集方式才能保證最優的性能。沒有固定收集器、參數組合,也沒有最優的調優方法,虛擬機也沒有什麼必然的內存回收行爲。因爲直到現在爲止還沒有最好的收集器出現,更加沒有萬能的收集器。

新生代收集器:Serial、ParNew、Parallel Scavenge
老年代收集器:CMS、Serial Old、Parallel Old
收集器適用場景:
用戶交互:ParNew、CMS
高吞吐量:Parallel Scavenge

gc-collects

上面有7中收集器,分爲兩塊,上面爲新生代收集器,下面是老年代收集器。如果兩個收集器之間存在連線,就說明它們可以搭配使用。

用文字描述收集器可配合使用結果如下:
Serial/Serial Old、Serial/CMS、ParNew/Serial Old、ParNew/CMS、Parallel Scavenge/Parallel Old、Parallel Scavenge/Serial Old、CMS/Serial Old

附錄:

垃圾收集器參數總結

1
-XX:+<option> 啓用選項
-XX:-<option> 不啓用選項
-XX:<option>=<number> 
-XX:<option>=<string>
參數 描述
-XX:+UseSerialGC Jvm運行在Client模式下的默認值,打開此開關後,使用Serial + Serial Old的收集器組合進行內存回收
-XX:+UseParNewGC 打開此開關後,使用ParNew + Serial Old的收集器進行垃圾回收
-XX:+UseConcMarkSweepGC 使用ParNew + CMS + Serial Old的收集器組合進行內存回收,Serial Old作爲CMS出現“Concurrent Mode Failure”失敗後的後備收集器使用。
-XX:+UseParallelGC Jvm運行在Server模式下的默認值,打開此開關後,使用Parallel Scavenge + Serial Old的收集器組合進行回收
-XX:+UseParallelOldGC 使用Parallel Scavenge + Parallel Old的收集器組合進行回收
-XX:SurvivorRatio 新生代中Eden區域與Survivor區域的容量比值,默認爲8,代表Eden:Subrvivor = 8:1
-XX:PretenureSizeThreshold 直接晉升到老年代對象的大小,設置這個參數後,大於這個參數的對象將直接在老年代分配
-XX:MaxTenuringThreshold 晉升到老年代的對象年齡,每次Minor GC之後,年齡就加1,當超過這個參數的值時進入老年代
-XX:UseAdaptiveSizePolicy 動態調整java堆中各個區域的大小以及進入老年代的年齡
-XX:+HandlePromotionFailure 是否允許新生代收集擔保,進行一次minor gc後, 另一塊Survivor空間不足時,將直接會在老年代中保留
-XX:ParallelGCThreads 設置並行GC進行內存回收的線程數
-XX:GCTimeRatio GC時間佔總時間的比列,默認值爲99,即允許1%的GC時間,僅在使用Parallel Scavenge 收集器時有效
-XX:MaxGCPauseMillis 設置GC的最大停頓時間,在Parallel Scavenge 收集器下有效
-XX:CMSInitiatingOccupancyFraction 設置CMS收集器在老年代空間被使用多少後出發垃圾收集,默認值爲68%,僅在CMS收集器時有效,-XX:CMSInitiatingOccupancyFraction=70
-XX:+UseCMSCompactAtFullCollection 由於CMS收集器會產生碎片,此參數設置在垃圾收集器後是否需要一次內存碎片整理過程,僅在CMS收集器時有效
-XX:+CMSFullGCBeforeCompaction 設置CMS收集器在進行若干次垃圾收集後再進行一次內存碎片整理過程,通常與UseCMSCompactAtFullCollection參數一起使用
-XX:+UseFastAccessorMethods 原始類型優化
-XX:+DisableExplicitGC 是否關閉手動System.gc
-XX:+CMSParallelRemarkEnabled 降低標記停頓
-XX:LargePageSizeInBytes 內存頁的大小不可設置過大,會影響Perm的大小,-XX:LargePageSizeInBytes=128m

Sun/oracle JDK GC組合方式

~ 新生代GC方式 老年代和持久代GC方式
-XX:+UseSerialGC Serial 串行GC Serial Old 串行GC
-XX:+UseParallelGC Parallel Scavenge 並行回收GC Serial Old 並行GC
-XX:+UseConcMarkSweepGC ParNew 並行GC CMS併發GC, 當出現“Concurrent Mode Failure”時採用Serial Old 串行GC
-XX:+UseParNewGC ParNew 並行GC Serial Old 串行GC
-XX:+UseParallelOldGC Parallel Scavenge 並行回收GC Parallel Old 並行GC
-XX:+UseConcMarkSweepGC -XX:+UseParNewGC Serial 串行GC CMS 併發GC 當出現“Concurrent Mode Failure”時採用Serial Old 串行GC

參考文章:
理解Java垃圾回收機制(1)
理解Java垃圾回收機制(2)
深入理解JVM : Java垃圾收集器

查看原文

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