产品大大:那么 CMS 既然这么优秀,是不是我们一直都在使用这个呢?
我:并不然,一般划时代的下场都不会很好,因为它存在了三个问题:
产品大大:那么它现在这么样了
我:它啊,在 JDK 9 中被标记为Deprecate,而在最新更新的 JDK 14 中彻底的退出了历史的舞台,此情可待成追忆,只是当时已惘然啊~
我:下面我来介绍一款当下我们在用的收集器吧,也就是鼎鼎大名的 G1 收集器 ~
G1 收集器
我:Garbage First 也称 G1,冷酷的外表,无情的性能,超前的设计,简直就是一个木得感情的杀手(biu~
产品大大:说人话(手动微笑脸
我: G1 收集器是又一个里程碑意义的收集器,它开创了收集器面向局部收集的设计思路和基于Region的内存布局方式。
产品大大:此话怎解?
我:在我们之前所了解的收集器中,我们都是基于内存分代理论,把内存区域分为老年代和新生代,不同区域的采用不同的收集器去完成,而G1颠覆了这个概念,它不再去区分所谓的老年代和新生代,而是面向全堆进行收集,把 Java 堆划分为多个大小相等的独立区域,在进行垃圾回收的时候,会将需要回收的区域组合成回收集(Collection Set),哪块儿内存存放的垃圾数量最多,回收收益最大,优先去回收那些收益最大的区域,这也是Garbage First 这个名字的由来~
产品大大:那么我有一个疑问,如果对象的大小过于庞大,一个区域无法放下这个对象的时候该怎么办呢?
我:首先说明一下,虽然化整为零,但是仍然保存了老年代和新生代的概念,只不过这一块儿不是一个固定的区域了,而是一系列区域的动态集合,而这些大对象会被存放在 N 个连续的 Humongous Region 中,这些 Region 被视为老年代的一部分~
产品大大:那么和CMS相比起来,它的优势在于什么地方呢?
我:相对于CMS来说,最根本的一点,CMS是基于「标记——清除」算法实现的,而 G1 是通过「标记——整理」算法,每个区域之间又是通过「标记——复制」算法,这样的做法不会产生大量的内存碎片,可以使程序更加长时间的稳定运行,省的因为出现大对象无法分配而去进行下一次 Full GC。
产品大大:那么 G1 的缺点其实也很明显,它的功能很强大,带来的是对内存的负荷和对CPU的压力,毕竟世界上没有免费的午餐~
我:没错呢,因为在处理跨 Region 引用的时候使用的卡表技术,标记——复制算法这些都会导致它的内存压力要比CMS高20%,但是不论是对于它所带来的提升和红利来说,还是对于一代新人换旧人的历史发展来说,我们无疑是更倾向于去选择 G1 的~
产品大大:嗯呐,下面还有嘛~
我:下面简单的介绍两款实验过程中的收集器吧,虽然不知道未来它们会怎么样,但是它们就像当年的 G1 的一样,未来可期~
产品大大:好的呢~
Shenandoah 收集器 && ZGC 收集器
我:下面简单介绍一下这两款低延迟收集器,在我们的收集器中,一般主要评判的标准有三种:内存占用。吞吐量。延迟,在这三者之中,我们最多可以在两个之间做到极致,随着我们计算机硬件的发展,内存占用慢慢没有那么重要,人们越来越看重延迟,所以低延迟就称为我们追求的目标,而这两款收集器就是为了达到GC只需 10ms 的目标去的~
产品大大:那么它们到底是什么呢?
我:一个叫做Shenandoah收集器,一个叫做ZGC收集器,它们两个功能非常相似,只不过 ZGC 是亲生的,而Shenandoah是抱养的,它们都可以看作是 G1 的继承者,G1 在一定程度上也对这两个代码有所借鉴和改进。
我:ZGC 收集器是一款基于 Region 内存布局的,(暂时)不设分代的,使用了读屏障,染色指针和内存多重映射等技术来实现可并发的标记——整理算法的,以低延迟为首要目标的一款垃圾收集器。它的技术实现,我这里就不再详细去讲了,等到它应用的比较广泛的时候,再去研究也不晚~
产品大大:行吧~ 那我们今天到这里,下次我们继续,我们现在出去撸串~