以前一篇Blog已經將GC的機制以及GC的算法講了一下。 html
而這篇Blog主要是討論這些GC的算法在JVM中的不一樣應用。 java
串行收集器是最古老,最穩定以及效率高的收集器
可能會產生較長的停頓,只使用一個線程去回收
-XX:+UseSerialGC 算法
0.844: [GC 0.844: [DefNew: 17472K->2176K(19648K), 0.0188339 secs] 17472K->2375K(63360K), 0.0189186 secs] [Times: user=0.01 sys=0.00, real=0.02 secs] 8.259: [Full GC 8.259: [Tenured: 43711K->40302K(43712K), 0.2960477 secs] 63350K->40302K(63360K), [Perm : 17836K->17836K(32768K)], 0.2961554 secs] [Times: user=0.28 sys=0.02, real=0.30 secs]
-XX:+UseParNewGC(new表明新生代,因此適用於新生代) 安全
Serial收集器新生代的並行版本
在新生代回收時使用複製算法
多線程,須要多核支持
-XX:ParallelGCThreads 限制線程數量 多線程
並行收集器的日誌輸出: 併發
0.834: [GC 0.834: [ParNew: 13184K->1600K(14784K), 0.0092203 secs] 13184K->1921K(63936K), 0.0093401 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
1.500: [Full GC [PSYoungGen: 2682K->0K(19136K)] [ParOldGen: 28035K->30437K(43712K)] 30717K->30437K(62848K) [PSPermGen: 10943K->10928K(32768K)], 0.2902791 secs] [Times: user=1.44 sys=0.03, real=0.30 secs]
-XX:MaxGCPauseMills
佈局
1. 初始標記(會產生全局停頓)
性能
CMS收集器的日誌輸出: spa
1.662: [GC [1 CMS-initial-mark: 28122K(49152K)] 29959K(63936K), 0.0046877 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 1.666: [CMS-concurrent-mark-start] 1.699: [CMS-concurrent-mark: 0.033/0.033 secs] [Times: user=0.25 sys=0.00, real=0.03 secs] 1.699: [CMS-concurrent-preclean-start] 1.700: [CMS-concurrent-preclean: 0.000/0.000 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 1.700: [GC[YG occupancy: 1837 K (14784 K)]1.700: [Rescan (parallel) , 0.0009330 secs]1.701: [weak refs processing, 0.0000180 secs] [1 CMS-remark: 28122K(49152K)] 29959K(63936K), 0.0010248 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 1.702: [CMS-concurrent-sweep-start] 1.739: [CMS-concurrent-sweep: 0.035/0.037 secs] [Times: user=0.11 sys=0.02, real=0.05 secs] 1.739: [CMS-concurrent-reset-start] 1.741: [CMS-concurrent-reset: 0.001/0.001 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]CMS收集器特色:
儘量下降停頓
會影響系統總體吞吐量和性能
.net
33.348: [Full GC 33.348: [CMS33.357: [CMS-concurrent-sweep: 0.035/0.036 secs] [Times: user=0.11 sys=0.03, real=0.03 secs] (concurrent mode failure): 47066K->39901K(49152K), 0.3896802 secs] 60771K->39901K(63936K), [CMS Perm : 22529K->22529K(32768K)], 0.3897989 secs] [Times: user=0.39 sys=0.00, real=0.39 secs]一旦 concurrent mode failure產生,將使用串行收集器做爲後備。
CMS也提供了整理碎片的參數:
-XX:+ UseCMSCompactAtFullCollection Full GC後,進行一次整理
G1是目前技術發展的最前沿成果之一,HotSpot開發團隊賦予它的使命是將來能夠替換掉JDK1.5中發佈的CMS收集器。
與CMS收集器相比G1收集器有如下特色:
1. 空間整合,G1收集器採用標記整理算法,不會產生內存空間碎片。分配大對象時不會由於沒法找到連續空間而提早觸發下一次GC。
2. 可預測停頓,這是G1的另外一大優點,下降停頓時間是G1和CMS的共同關注點,但G1除了追求低停頓外,還能創建可預測的停頓時間模型,能讓使用者明確指定在一個長度爲N毫秒的時間片斷內,消耗在垃圾收集上的時間不得超過N毫秒,這幾乎已是實時Java(RTSJ)的垃圾收集器的特徵了。
上面提到的垃圾收集器,收集的範圍都是整個新生代或者老年代,而G1再也不是這樣。使用G1收集器時,Java堆的內存佈局與其餘收集器有很大差異,它將整個Java堆劃分爲多個大小相等的獨立區域(Region),雖然還保留有新生代和老年代的概念,但新生代和老年代再也不是物理隔閡了,它們都是一部分(能夠不連續)Region的集合。
G1的新生代收集跟ParNew相似,當新生代佔用達到必定比例的時候,開始出發收集。
和CMS相似,G1收集器收集老年代對象會有短暫停頓。
步驟:
GC的停頓主要來源於可達性分析上,程序執行時並不是在全部地方都能停頓下來開始GC,只有在到達安全點時才能暫停。
安全點的選定基本上是以程序「是否具備讓程序長時間執行的特徵」爲標準進行選定的——由於每條指令執行的時間都很是短暫,程序不太可能由於指令流長度太長這個緣由而過長時間運行,「長時間執行」的最明顯特徵就是指令序列複用,例如方法調用、循環跳轉、異常跳轉等,因此具備這些功能的指令纔會產生安全點。
接下來的問題就在於,如何讓程序在須要GC時都跑到安全點上停頓下來,大多數JVM的實現都是採用主動式中斷的思想。
主動式中斷的思想是當GC須要中斷線程的時候,不直接對線程操做,僅僅簡單地設置一個標誌,各個線程執行時主動去輪詢這個標誌,發現中斷標誌爲真時就本身中斷掛起,輪詢標誌的地方和安全點是重合的,另外再加上建立對象須要分配內存的地方。
只要記住流行的組合就這幾種狀況
Serial
ParNew + CMS
ParallelYoung + ParallelOld
G1GC
2. http://www.importnew.com/15311.html
3. http://www.zhihu.com/question/30538696