在jvm中,實現了多種垃圾收集器,包括:串行垃圾收集器、並行垃圾收集器、CMS(併發)垃圾收集器、G1垃圾收集器,接下來,咱們一個個的瞭解學習。java
串行垃圾收集器web
串行垃圾收集器,是指使用單線程進行垃圾回收,垃圾回收時,只有一個線程在工做,算法
而且java應用中的全部線程都要暫停,等待垃圾回收的完成。這種現象稱之爲STW(Stop-The-World)。多線程
對於交互性較強的應用而言,這種垃圾收集器是不可以接受的。併發
通常在Javaweb應用中是不會採用該收集器的。oracle
編寫測試代碼dom
package com.wish; import java.util.ArrayList; import java.util.List; import java.util.Properties; import java.util.Random; public class TestGC { public static void main(String[] args) throws Exception { List<Object> list = new ArrayList<Object>(); while (true) { int sleep = new Random().nextInt(100); if (System.currentTimeMillis() % 2 == 0) { list.clear(); } else { for (int i = 0; i < 10000; i++) { Properties properties = new Properties(); properties.put("key_" + i, "value_" + System.currentTimeMillis() + i); list.add(properties); } } // System.out.println("list大小爲:" + list.size()); Thread.sleep(sleep); } } }
設置垃圾回收爲串行收集器jvm
在程序運行參數中添加2個參數,以下:性能
# 爲了測試GC,將堆的初始和最大內存都設置爲16M -XX:+UseSerialGC -XX:+PrintGCDetails -Xms16m -Xmx16m
啓動程序,能夠看到下面信息:學習
GC日誌信息解讀:
年輕代的內存GC先後的大小:
並行垃圾收集器
並行垃圾收集器在串行垃圾收集器的基礎之上作了改進,將單線程改成了多線程進行垃圾回收,這樣能夠縮短垃圾回收的時間。
(這裏是指,並行能力較強的機器)
固然了,並行垃圾收集器在收集的過程當中也會暫停應用程序,這個和串行垃圾回收器是同樣的,只是並行執行,速度更快些,暫停的時間更短一些。
ParNew垃圾收集器
ParNew垃圾收集器是工做在年輕代上的,只是將串行的垃圾收集器改成了並行。
經過-XX:+UseParNewGC參數設置年輕代使用ParNew回收器,老年代使用的依然是串行收集器。
測試:
#參數 -XX:+UseParNewGC -XX:+PrintGCDetails -Xms16m -Xmx16m
由以上信息能夠看出, ParNew: 使用的是ParNew收集器。其餘信息和串行收集器一致。
ParallelGC垃圾收集器
ParallelGC收集器工做機制和ParNewGC收集器同樣,只是在此基礎之上,新增了兩個和系統吞吐量相關的參數,使得其使用起來更加的靈活和高效。
相關參數以下:
通常用於,手動調整參數比較困難的場景,讓收集器自動進行調整。
測試
#參數 -XX:+UseParallelGC -XX:+UseParallelOldGC -XX:MaxGCPauseMillis=100 -XX:+PrintGCDetails -Xms16m -Xmx16m
啓動
有以上信息能夠看出,年輕代和老年代都使用了ParallelGC垃圾回收
CMS垃圾收集器
CMS全稱 Concurrent Mark Sweep,是一款併發的、使用標記-清除算法的垃圾回收器,該回收器是針對老年代垃圾回收的,經過參數-XX:+UseConcMarkSweepGC進行設置。
CMS垃圾回收器的執行過程以下:
測試
#設置啓動參數 ‐XX:+UseConcMarkSweepGC ‐XX:+PrintGCDetails ‐Xms16m ‐Xmx16m
由以上日誌信息,能夠看出CMS執行的過程。
G1垃圾收集器
G1垃圾收集器是在jdk1.7中正式使用的全新的垃圾收集器,oracle官方計劃在jdk9中將G1變成默認的垃圾收集器,以替代CMS。
G1的設計原則就是簡化JVM性能調優,開發人員只須要簡單的三步便可完成調優:
1. 第一步,開啓G1垃圾收集器
2. 第二步,設置堆的最大內存
3. 第三步,設置最大的停頓時間
G1中提供了三種模式垃圾回收模式,Young GC、Mixed GC 和 Full GC,在不一樣的條件下被觸發。
原理
G1垃圾收集器相對比其餘收集器而言,最大的區別在於它取消了年輕代、老年代的物理劃分,
取而代之的是將堆劃分爲若干個區域(Region),這些區域中包含了有邏輯上的年輕代、老年代區域。
這樣作的好處就是,咱們不再用單獨的空間對每一個代進行設置了,不用擔憂每一個代內存是否足夠。
在G1劃分的區域中,年輕代的垃圾收集依然採用暫停全部應用線程的方式,將存活對象拷貝到老年代或者Survivor空間,
G1收集器經過將對象從一個區域複製到另一個區域,完成了清理工做。
這就意味着,在正常的處理過程當中,G1完成了堆的壓縮(至少是部分堆的壓縮),這樣也就不會有cms內存碎片問題的存在了。
在G1中,有一種特殊的區域,叫Humongous區域。
Young GC
Young GC主要是對Eden區進行GC,它在Eden空間耗盡時會被觸發。
Remembered Set(已記憶集合)
在GC年輕代的對象時,咱們如何找到年輕代中對象的根對象呢?
根對象多是在年輕代中,也能夠在老年代中,那麼老年代中的全部對象都是根麼?
若是全量掃描老年代,那麼這樣掃描下來會耗費大量的時間。
因而,G1引進了RSet的概念。它的全稱是Remembered Set,其做用是跟蹤指向某個堆內的對象引用。
每一個Region初始化時,會初始化一個RSet,該集合用來記錄並跟蹤其它Region指向該
Region中對象的引用,每一個Region默認按照512Kb劃分紅多個Card,因此RSet須要記錄的東西應該是 xx Region的 xx Card。
Mixed GC
當愈來愈多的對象晉升到老年代old region時,爲了不堆內存被耗盡,虛擬機會觸發一個混合的垃圾收集器,
即Mixed GC,該算法並非一個Old GC,除了回收整個YoungRegion,還會回收一部分的Old Region,
這裏須要注意:是一部分老年代,而不是所有老年代,能夠選擇哪些old region進行收集,從而能夠對垃圾回收的耗時時間進行控制。
也要注意的是Mixed GC 並非 Full GC。
MixedGC何時觸發?
由參數 -XX:InitiatingHeapOccupancyPercent=n 決定。默認:45%,該參數的意思是:當老年代大小佔整個堆大小百分比達到該閥值時觸發。
它的GC步驟分2步:
1.全局併發標記(global concurrent marking)
2. 拷貝存活對象(evacuation)
全局併發標記
全局併發標記,執行過程分爲五個步驟:
拷貝存活對象
Evacuation階段是全暫停的。該階段把一部分Region裏的活對象拷貝到另外一部分Region中,從而實現垃圾的回收清理。
G1收集器相關參數
測試
#參數 ‐XX:+UseG1GC ‐XX:MaxGCPauseMillis=100 ‐XX:+PrintGCDetails ‐Xmx256m
對於G1垃圾收集器優化建議