學習了GC算法的相關概念以後, 咱們將介紹在JVM中這些算法的具體實現。首先要記住的是, 大多數JVM都須要使用兩種不一樣的GC算法 —— 一種用來清理年輕代, 另外一種用來清理老年代。html
咱們能夠選擇JVM內置的各類算法。若是不經過參數明確指定垃圾收集算法, 則會使用宿主平臺的默認實現。本章會詳細介紹各類算法的實現原理。java
下面是關於Java 8中各類組合的垃圾收集器概要列表,對於以前的Java版原本說,可用組合會有一些不一樣:git
Young | Tenured | JVM options |
---|---|---|
Incremental(增量GC) | Incremental | -Xincgc |
Serial | Serial | -XX:+UseSerialGC |
Parallel Scavenge | Serial | -XX:+UseParallelGC -XX:-UseParallelOldGC |
Parallel New | Serial | N/A |
Serial | Parallel Old | N/A |
Parallel Scavenge | Parallel Old | -XX:+UseParallelGC -XX:+UseParallelOldGC |
Parallel New | Parallel Old | N/A |
Serial | CMS | -XX:-UseParNewGC -XX:+UseConcMarkSweepGC |
Parallel Scavenge | CMS | N/A |
Parallel New | CMS | -XX:+UseParNewGC -XX:+UseConcMarkSweepGC |
G1 | -XX:+UseG1GC |
看起來有些複雜, 不用擔憂。主要使用的是上表中黑體字表示的這四種組合。其他的要麼是被廢棄(deprecated), 要麼是不支持或者是不太適用於生產環境。因此,接下來咱們只介紹下面這些組合及其工做原理:github
Serial GC 對年輕代使用 mark-copy(標記-複製) 算法, 對老年代使用 mark-sweep-compact(標記-清除-整理)算法. 顧名思義, 二者都是單線程的垃圾收集器,不能進行並行處理。二者都會觸發全線暫停(STW),中止全部的應用線程。算法
所以這種GC算法不能充分利用多核CPU。無論有多少CPU內核, JVM 在垃圾收集時都只能使用單個核心。安全
要啓用此款收集器, 只須要指定一個JVM啓動參數便可,同時對年輕代和老年代生效:服務器
java -XX:+UseSerialGC com.mypackages.MyExecutableClass
該選項只適合幾百MB堆內存的JVM,並且是單核CPU時比較有用。 對於服務器端來講, 由於通常是多個CPU內核, 並不推薦使用, 除非確實須要限制JVM所使用的資源。大多數服務器端應用部署在多核平臺上, 選擇 Serial GC 就表示人爲的限制系統資源的使用。 致使的就是資源閒置, 多的CPU資源也不能用來下降延遲,也不能用來增長吞吐量。數據結構
下面讓咱們看看Serial GC的垃圾收集日誌, 並從中提取什麼有用的信息。爲了打開GC日誌記錄, 咱們使用下面的JVM啓動參數:多線程
-XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps
產生的GC日誌輸出相似這樣(爲了排版,已手工折行):併發
2015-05-26T14:45:37.987-0200: 151.126: [GC (Allocation Failure) 151.126: [DefNew: 629119K->69888K(629120K), 0.0584157 secs] 1619346K->1273247K(2027264K), 0.0585007 secs] [Times: user=0.06 sys=0.00, real=0.06 secs] 2015-05-26T14:45:59.690-0200: 172.829: [GC (Allocation Failure) 172.829: [DefNew: 629120K->629120K(629120K), 0.0000372 secs] 172.829: [Tenured: 1203359K->755802K(1398144K),