这篇博客, 主要介绍 jvm 常见的 gc 收集器及其搭配. gc收集器, 是 gc 算法和策略的实现, 主要的 gc 算法已经在之前简单提到过(传送门) , 今天也会涉及到大部分. 接下来, 我们就看看有哪些常见的 gc 收集器.
年轻代收集器
Serial 复制收集器 :
使用-XX:+UseSerialGC
来启用, 穿行复制收集器, 单线程, 复制存活对象从Eden->Survivor
和Survivor->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