Jvm垃圾回收
Table of Contents
概念
GC
- 常被使用的垃圾回收器有 CMS 和 G1,但 JVM 还有其他几个常见的垃圾回收器。
- 垃圾回收,首先就需要找到这些垃圾,然后回收掉。但是 GC 过程正好相反,它是先找到活跃的对象,然后把其他不活跃的对象判定为垃圾,然后删除。所以垃圾回收只与活跃的对象有关,和堆得大小无关。
年轻代
- 年轻代使用的垃圾回收算法是复制算法。因为年轻代发生 GC 后,只会有非常少的对象存活,复制这部分对象是非常高效的。
老年代
- 老年代一般使用“标记-清除”、“标记-整理”算法,因为老年代的对象存活率一般是比较高的,空间又比较大,拷贝起来并不划算,还不如采取就地收集的方式。
年轻代垃圾回收器
(1)Serial 垃圾收集器
- 处理 GC 的只有一条线程,并且在垃圾回收的过程中暂停一切用户线程。
(2)ParNew 垃圾收集器
ParNew 是 Serial 的多线程版本。由多条 GC 线程并行地进行垃圾清理。清理过程依然要停止用户线程。
(3)Parallel Scavenge 垃圾收集器
- 另一个多线程版本的垃圾回收器。它与 ParNew 的主要区别是:
- Parallel Scavenge:追求 CPU 吞吐量,能够在较短时间内完成指定任务,适合没有交互的后台计算。弱交互强计算。
- ParNew:追求降低用户停顿时间,适合交互式应用。强交互弱计算。
老年代垃圾收集器
(1)Serial Old 垃圾收集器
- 与年轻代的 Serial 垃圾收集器对应,都是单线程版本,同样适合客户端使用。
- 年轻代的 Serial,使用复制算法。
- 老年代的 Old Serial,使用标记-整理算法。
(2)Parallel Old
- Parallel Old 收集器是 Parallel Scavenge 的老年代版本,追求 CPU 吞吐量。
(3)CMS 垃圾收集器
CMS(Concurrent Mark Sweep)收集器是以获取最短 GC 停顿时间为目标的收集器,它在垃圾收集时使得用户线程和 GC 线程能够并发执行,因此在垃圾收集过程中用户也不会感到明显的卡顿。我们会在后面的课时详细介绍它。
- 长期来看,CMS 垃圾回收器,是要被 G1 等垃圾回收器替换掉的。在 Java8 之后,使用它将会抛出一个警告。
- Java HotSpot(TM) 64-Bit Server VM warning: Option UseConcMarkSweepGC was deprecated in version 9.0 and will likely be removed in a future release.
配置参数
通过 -XX:+PrintCommandLineFlags 参数,可以查看当前 Java 版本默认使用的垃圾回收器。你可以看下我的系统中 Java13 默认的收集器就是 G1。
java -XX:+PrintCommandLineFlags -version
STW(stop the world)
小结
本文章的内容很多。由于篇幅有限,我们仅介绍了最重要的点,要是深挖下去,估计一本书都写不完。
归根结底,各色的垃圾回收器就是为了解决头疼的 STW 问题,让 GC 时间更短,停顿更小,吞吐量更大。
现在的回收器,基于弱代假设,大多是分代回收的理念。针对年轻代和老年代,有多种不同的垃圾回收算法,有些可以组合使用。
我们尤其讲解了年轻代的垃圾回收。
- 年轻代是 GC 的重灾区,大部分对象活不到老年代;
- 面试经常问,都是些非常朴素的原理;
- 为我们后面对 G1 和 ZGC 的介绍打下基础。
我们也接触了大量的名词。让我们来总结一下:
算法
- Mark
- Sweep
- Copy
- Compact
分代
- Young generation
- Survivor
- Eden
- Old generation | Tenured Generation
- GC
Minor GC
Major GC
名词
- weak generational hypothesis
- 分配担保
- 提升
- 卡片标记
- STW