【JVM】 常用的 GC 收集器

这篇博客, 主要介绍 jvm 常见的 gc 收集器及其搭配. gc收集器, 是 gc 算法和策略的实现, 主要的 gc 算法已经在之前简单提到过(传送门) , 今天也会涉及到大部分. 接下来, 我们就看看有哪些常见的 gc 收集器.

年轻代收集器


Serial 复制收集器 :


使用-XX:+UseSerialGC来启用, 穿行复制收集器, 单线程, 复制存活对象从Eden->SurvivorSurvivor->Survivor, 并决定什么时候复制到老年代中.

ParNew 收集器


使用-XX:+UseParNewGC来启用, ParNew 是 Serial 复制收集器的多线程版, 内部有一个回调可以让老年代收集器来处理它收集到的对象, 因此 ParNew 可以和 CMS 收集器配合工作.

PS Scavenge 收集器


使用-XX:+UseParallelGC来启用, 并行收集器, 也是使用复制算法的收集器, 不过它号称是吞吐量优先的收集器, 并提供了两个参数控制吞吐量:

-XX:MaxGCPauseMillis
控制最大垃圾回收时间

-XX:GCTimeRatio
吞吐量大小

还有一个参数 -XX:+UseAdaptiveSizePolicy
打开之后可以不用设置新生代大小以及Eden和Survivor的比例, jvm会根据当前收集到的监控信息, 动态调整这些参数以提供最合适的停顿时间和最大的吞吐量, 这也称为 GC的自适应调节策略 ( GC Ergonomics ), 这也是和ParNew的一大区别.

G1 Young 收集器


使用-XX:+UseG1GC来启用, 使用Garbage First算法把堆分割成许多更小的空间 ( Region ) , 不过仍然保留了 Eden 和 Survivor 的划分方法, 并在GC时优先回收价值最大的 Region, 因此称为 Garbage First.

老年代收集器


Serial Old (Old MarkSweepCompact) 收集器


使用-XX:+UseSerialGC来启用, 实现MarkSweepCompact标记整理算法.

PS MarkSweep 收集器


使用-XX:+UseParallelOldGC来启用, MarkSweepCompact 的多线程版.

ConcurrentMarkSweep (CMS) 收集器


使用-XX:+UseConcMarkSweepGC来启用, CMS 的目标是让更多的GC在后台跑而不用stop-the-world, 在concurrent mode失败时, 退化到 Serial Old 收集器.
不知有没有注意到, CMS 的名称是 Concurrent, 而不是 Parallel. Concurrent 是并发, 用户线程和GC线程是同时执行的, 但 Parallel 是用户线程等待而多条GC线程在工作.

G1 Mixed Generation 收集器


使用-XX:+UseG1GC来启用.

收集器搭配组合


下表列出了大部分的收集器组合:

参数选项 对应的收集器组合
-XX:+UseSerialGC young serial and old serial MarkSweepCompact , 适合客户端使用, 单线程节省开销
-XX:+UseG1GC young G1 Young and old G1 Mixed
-XX:+UseParallelGC -XX:+UseParallelOldGC -XX:-UseAdaptiveSizePolicy young PS Scavenge old PS MarkSweep, 没有自适应调节, 适合吞吐量优先/CPU敏感的场合, tomcat 默认使用的
-XX:+UseParallelGC -XX:+UseParallelOldGC -XX:+UseAdaptiveSizePolicy young PS Scavenge old PS MarkSweep, 自适应调节
-XX:+UseConcMarkSweepGC -XX:+UseParNewGC young ParNew old ConcurrentMarkSweep** , GC 时间有限
-XX:+UseParNewGC (deprecated in Java 8 and removed in Java 9 ) young ParNew old serial MarkSweepCompact
-XX:+UseConcMarkSweepGC -XX:-UseParNewGC (deprecated in Java 8 and removed in Java 9) young Serial old ConcurrentMarkSweep**

参考


Oracle JVM Garbage Collectors Available From JDK 1.7.0_04 And After