jvm中的垃圾收集器簡介

0 概述

現代JVM的類型繁多,最主流的四個垃圾收集器Serial收集器、 Parallel / Throughput收集器、Concurrent收集器(CMS)和G1收集器。這四種垃圾收集器各有各的特點,需要我們根據自己的實際應用場景選擇合適的垃圾收集器。雖然存在差異但是它們也有很多共性:1)所有的垃圾收集器都將堆劃分爲老年代和新生代(分代收集)2)所有的垃圾收集器在清理新生代對象時候,都使用了(stop-the-world)方式的垃圾收集方法。本文也是主要對着這四種垃圾收集器進行簡單的介紹。

1 Serial收集器

Serial收集器是一個單線程的收集器,使用Serial收集器時候無論是進行Minor GC,還是進行Full GC ,清理堆空間時,所有的應用線程都會被暫停。進行Full GC時候,它還會對老年代對象進行壓縮整理。其比較適合於單核處理器(因爲是單線程不能充分利用多核處理器硬件);啓用方式:-XX:+UseSerialGC(打開此開關後,使用Serial + Serial Old的收集器組合進行內存回收)。

public class CollectorTest {
    private static final int _1MB = 1024 * 1024;


    /**
     *-verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:SurvivorRatio=8 -XX:+PrintGCDetails -XX:+UseSerialGC
     *
     *
     * @param args
     */
    public static void main(String[] args) throws Exception {


        byte[] bytes1 = new byte[5*_1MB];
        byte[] bytes3 = new byte[5* _1MB];

    }

}

可以看出,DefNew表示使用Serial收集器。
[GC (Allocation Failure) [DefNew: 7182K->402K(9216K), 0.0056138 secs] 7182K->5522K(19456K), 0.0056532 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 
Heap
 def new generation   total 9216K, used 5689K [0x00000007bec00000, 0x00000007bf600000, 0x00000007bf600000)
  eden space 8192K,  64% used [0x00000007bec00000, 0x00000007bf1299e0, 0x00000007bf400000)
  from space 1024K,  39% used [0x00000007bf500000, 0x00000007bf564a60, 0x00000007bf600000)
  to   space 1024K,   0% used [0x00000007bf400000, 0x00000007bf400000, 0x00000007bf500000)
 tenured generation   total 10240K, used 5120K [0x00000007bf600000, 0x00000007c0000000, 0x00000007c0000000)
   the space 10240K,  50% used [0x00000007bf600000, 0x00000007bfb00010, 0x00000007bfb00200, 0x00000007c0000000)
 Metaspace       used 3298K, capacity 4496K, committed 4864K, reserved 1056768K
  class space    used 368K, capacity 388K, committed 512K, reserved 1048576K

2 Parallel收集器

Parallel 收集器也成爲Throughput收集器,它是Server級虛擬機的默認收集器。Parallel 收集器是Serial收集器多線程版。因此在多核處理器要比Serial收集器快很多。Throughput收集器在Minor GC 和Full GC 時候會暫停所有的應用線程,同時在Full GC時候,它還會對老年代對象進行壓縮整理。啓用方式:-XX:+UseParallelGC(開啓此參數使用parallel scavenge & parallel old蒐集器),-XX:+UseParallelOldGC。
- Parallel Scavenge收集器,新生代收集使用,其可控制吞吐量(與ParNew收集器的唯一區別)。
- Parallel Old收集器,老年代收集使用。

public class CollectorTest {
    private static final int _1MB = 1024 * 1024;


    /**
     * -verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:SurvivorRatio=8 -XX:+PrintGCDetails  -XX:-UseParallelGC 
     *
     * @param args
     */
    public static void main(String[] args) throws Exception {


        byte[] bytes1 = new byte[4* _1MB];
        byte[] bytes2 = new byte[4 * _1MB];
        byte[] bytes3 = new byte[4 * _1MB];
        bytes2=null;
        byte[] bytes4 = new byte[2* _1MB];

    }

}
可以看出PSYoungGen、ParOldGen爲 Parallel收集器。
[GC (Allocation Failure) --[PSYoungGen: 6158K->6158K(9216K)] 14350K->14358K(19456K), 0.0014680 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] 
[Full GC (Ergonomics) [PSYoungGen: 6158K->0K(9216K)] [ParOldGen: 8200K->8618K(10240K)] 14358K->8618K(19456K), [Metaspace: 3306K->3306K(1056768K)], 0.0064933 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 
Heap
 PSYoungGen      total 9216K, used 2130K [0x00000007bf600000, 0x00000007c0000000, 0x00000007c0000000)
  eden space 8192K, 26% used [0x00000007bf600000,0x00000007bf814930,0x00000007bfe00000)
  from space 1024K, 0% used [0x00000007bff00000,0x00000007bff00000,0x00000007c0000000)
  to   space 1024K, 0% used [0x00000007bfe00000,0x00000007bfe00000,0x00000007bff00000)
 ParOldGen       total 10240K, used 8618K [0x00000007bec00000, 0x00000007bf600000, 0x00000007bf600000)
  object space 10240K, 84% used [0x00000007bec00000,0x00000007bf46ab60,0x00000007bf600000)
 Metaspace       used 3313K, capacity 4496K, committed 4864K, reserved 1056768K
  class space    used 369K, capacity 388K, committed 512K, reserved 1048576K

3 CMS收集器

CMS 收集器設計的初衷是爲了消除Parallel收集器和Serial收集器Full GC 週期中的長時間的停頓。CMS收集器在Minor GC時會暫停所有的應用線程,並以多線程的方式進行垃圾回收,CMS不在使用Parallel的收集算法,改用新的算法(ParNew)來收集新生代。CMS 收集器在Full GC 時候不在暫停應用線程,而是使用若干個後臺線程定期對老年代空間進行掃描,及時回收其中不在使用的對象。CMS收集器優點是併發收集、低停頓。缺點容易產生碎片(標記清除算法)、佔用CPU資源。啓用方式: -XX:+UseConcMarkSweepGC(使用ParNew & CMS,serial old爲替補)。

public class CollectorTest {
    private static final int _1MB = 1024 * 1024;


    /**
     * -verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:SurvivorRatio=8 -XX:+PrintGCDetails  -XX:+UseConcMarkSweepGC
     *
     * @param args
     */
    public static void main(String[] args) throws Exception {


        byte[] bytes1 = new byte[4* _1MB];
        byte[] bytes2 = new byte[4 * _1MB];
        byte[] bytes3 = new byte[4 * _1MB];
        bytes2=null;
        byte[] bytes4 = new byte[2* _1MB];

    }

}

[GC (Allocation Failure) [ParNew: 6159K->419K(9216K), 0.0089901 secs] 6159K->4517K(19456K), 0.0090417 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 
[GC (Allocation Failure) [ParNew: 4599K->502K(9216K), 0.0038158 secs] 8697K->8696K(19456K), 0.0038497 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC (CMS Initial Mark) [1 CMS-initial-mark: 8194K(10240K)] 15133K(19456K), 0.0010468 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[CMS-concurrent-mark-start]
[CMS-concurrent-mark: 0.000/0.000 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
[CMS-concurrent-preclean-start]
[CMS-concurrent-preclean: 0.000/0.000 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[CMS-concurrent-abortable-preclean-start]
[CMS-concurrent-abortable-preclean: 0.000/0.000 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
Heap
 par new generation   total 9216K, used 6938K [0x00000007bec00000, 0x00000007bf600000, 0x00000007bf600000)
  eden space 8192K,  78% used [0x00000007bec00000, 0x00000007bf249058, 0x00000007bf400000)
  from space 1024K,  49% used [0x00000007bf400000, 0x00000007bf47dba0, 0x00000007bf500000)
  to   space 1024K,   0% used [0x00000007bf500000, 0x00000007bf500000, 0x00000007bf600000)
 concurrent mark-sweep generation total 10240K, used 8194K [0x00000007bf600000, 0x00000007c0000000, 0x00000007c0000000)
 Metaspace       used 3290K, capacity 4496K, committed 4864K, reserved 1056768K
  class space    used 365K, capacity 388K, committed 512K, reserved 1048576K
[GC (CMS Final Remark) [YG occupancy: 6938 K (9216 K)][Rescan (parallel) , 0.0008426 secs][weak refs processing, 0.0000090 secs][class unloading, 0.0003863 secs][scrub symbol table, 0.0008789 secs][scrub string table, 0.0001825 secs][1 CMS-remark: 8194K(10240K)] 15133K(19456K), 0.0023860 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 

4 G1收集器

G1收集器屬於Concurrent收集器,用於大堆區域;新生代的垃圾收集依然採用暫停應用線程的方式,老年代的垃圾收集工作由後臺線程完成。由於G1收集器基於Mark-Compact算法,劃分多個大小固定的區域,不會產生碎片。啓用方式: -XX:+UseG1GC 。

public class CollectorTest {
    private static final int _1MB = 1024 * 1024;


    /**
     * -verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:SurvivorRatio=8 -XX:+PrintGCDetails  -XX:+UseG1GC
     *
     * @param args
     */
    public static void main(String[] args) throws Exception {


        byte[] bytes1 = new byte[4* _1MB];
        byte[] bytes2 = new byte[4 * _1MB];
        byte[] bytes3 = new byte[4 * _1MB];
        bytes2=null;
        byte[] bytes4 = new byte[2* _1MB];

    }

}

[GC pause (G1 Humongous Allocation) (young) (initial-mark), 0.0017483 secs]
   [Parallel Time: 1.2 ms, GC Workers: 4]
      [GC Worker Start (ms): Min: 346.0, Avg: 346.0, Max: 346.0, Diff: 0.0]
      [Ext Root Scanning (ms): Min: 0.6, Avg: 0.6, Max: 0.6, Diff: 0.0, Sum: 2.3]
      [Update RS (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
         [Processed Buffers: Min: 0, Avg: 0.0, Max: 0, Diff: 0, Sum: 0]
      [Scan RS (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
      [Code Root Scanning (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
      [Object Copy (ms): Min: 0.5, Avg: 0.5, Max: 0.6, Diff: 0.0, Sum: 2.2]
      [Termination (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
         [Termination Attempts: Min: 1, Avg: 1.8, Max: 4, Diff: 3, Sum: 7]
      [GC Worker Other (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.1]
      [GC Worker Total (ms): Min: 1.1, Avg: 1.1, Max: 1.2, Diff: 0.0, Sum: 4.6]
      [GC Worker End (ms): Min: 347.1, Avg: 347.1, Max: 347.1, Diff: 0.0]
   [Code Root Fixup: 0.0 ms]
   [Code Root Purge: 0.0 ms]
   [Clear CT: 0.2 ms]
   [Other: 0.3 ms]
      [Choose CSet: 0.0 ms]
      [Ref Proc: 0.1 ms]
      [Ref Enq: 0.0 ms]
      [Redirty Cards: 0.0 ms]
      [Humongous Register: 0.0 ms]
      [Humongous Reclaim: 0.0 ms]
      [Free CSet: 0.0 ms]
   [Eden: 2048.0K(10.0M)->0.0B(9216.0K) Survivors: 0.0B->1024.0K Heap: 6144.0K(20.0M)->4580.9K(20.0M)]
 [Times: user=0.00 sys=0.00, real=0.01 secs] 
[GC concurrent-root-region-scan-start]
[GC concurrent-root-region-scan-end, 0.0007369 secs]
[GC concurrent-mark-start]
[GC concurrent-mark-end, 0.0000357 secs]
[GC remark [Finalize Marking, 0.0000582 secs] [GC ref-proc, 0.0000332 secs] [Unloading, 0.0006383 secs], 0.0008605 secs]
 [Times: user=0.01 sys=0.00, real=0.00 secs] 
[GC cleanup 12M->12M(20M), 0.0005868 secs]
 [Times: user=0.00 sys=0.00, real=0.00 secs] 
[GC pause (G1 Humongous Allocation) (young), 0.0010836 secs]
   [Parallel Time: 0.6 ms, GC Workers: 4]
      [GC Worker Start (ms): Min: 356.2, Avg: 356.2, Max: 356.2, Diff: 0.0]
      [Ext Root Scanning (ms): Min: 0.2, Avg: 0.2, Max: 0.3, Diff: 0.1, Sum: 0.8]
      [Update RS (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
         [Processed Buffers: Min: 0, Avg: 0.0, Max: 0, Diff: 0, Sum: 0]
      [Scan RS (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
      [Code Root Scanning (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
      [Object Copy (ms): Min: 0.3, Avg: 0.3, Max: 0.4, Diff: 0.1, Sum: 1.4]
      [Termination (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
         [Termination Attempts: Min: 1, Avg: 1.8, Max: 3, Diff: 2, Sum: 7]
      [GC Worker Other (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
      [GC Worker Total (ms): Min: 0.6, Avg: 0.6, Max: 0.6, Diff: 0.0, Sum: 2.3]
      [GC Worker End (ms): Min: 356.8, Avg: 356.8, Max: 356.8, Diff: 0.0]
   [Code Root Fixup: 0.0 ms]
   [Code Root Purge: 0.0 ms]
   [Clear CT: 0.0 ms]
   [Other: 0.4 ms]
      [Choose CSet: 0.0 ms]
      [Ref Proc: 0.1 ms]
      [Ref Enq: 0.0 ms]
      [Redirty Cards: 0.0 ms]
      [Humongous Register: 0.0 ms]
      [Humongous Reclaim: 0.0 ms]
      [Free CSet: 0.3 ms]
   [Eden: 1024.0K(9216.0K)->0.0B(9216.0K) Survivors: 1024.0K->1024.0K Heap: 12.7M(20.0M)->8834.5K(20.0M)]
 [Times: user=0.00 sys=0.00, real=0.01 secs] 
Heap
 garbage-first heap   total 20480K, used 10882K [0x00000007bec00000, 0x00000007bed000a0, 0x00000007c0000000)
  region size 1024K, 2 young (2048K), 1 survivors (1024K)
 Metaspace       used 3313K, capacity 4496K, committed 4864K, reserved 1056768K
  class space    used 369K, capacity 388K, committed 512K, reserved 1048576K

參考文獻
[1] 深入理解java 虛擬機(第二版),周志明著
[2] java 性能權威指南,Scott Oaks著

發佈了199 篇原創文章 · 獲贊 111 · 訪問量 53萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章