00:00
接下来啊,咱们来看一下这个CMS呢,垃圾回收器,诶它的主要特点呢,我们说叫主打叫低延迟啊,或者也称为呢叫低的暂停时间,好,我们来介绍一下这个垃圾回收器说呢,在这个JDK1.5的时候啊house bar呢推出了一款在强交互应用当中啊,几乎可以认为呢是具有划时代意义的啊垃圾回收器哎称为呢叫CMS,那CMS呢,自然而然呢,就是我们这几个单词的一个首字母了,哎这几个单词呢,也非常具有代表意义,首先的话呢,叫concurrent,哎这个呢,我们能够明显看出来它是一个并发的垃圾回收器,它呢不是叫这个parallel对吧?诶这叫并发性啊然后呢,这个MS呢,对应的叫mark sweep,诶这个呢,正好对应的是咱们前面讲的叫标记清除算法。所以说呢,我们这个CMS呢,这几个单词呢,非常具有代表性啊,指出了它的一个主要特点,说呢,这款收集器呢,是household虚拟机,说第一款真正意义上呢叫并发的收集器,那前面呢,咱们提到过,在垃圾回收方面,什么叫并发呢,就是说呢,我们这个用户线程啊,比如我们这个红色的表示的这叫三条用户线程,然后呢,我这个蓝色呢,表示的叫垃圾回收线程,它们呢是可以我们说呢叫诶同时执行对吧?诶我们称为了这个叫并发的一个垃圾回收器,诶第一次实现了让垃圾回收线程和用户线程呢,可以同时的去工作。
01:16
诶同时的去工作,那么前面的话呢,咱们是呃主要讲了这一个,诶piel或者呢叫parallel是吧,Parallel和parallel old哎这样的两个,这个新生代和老年代垃圾回收器啊,而且呢,这两个垃圾回收器的一个组合呀,我们说在这个server模式下的话呢,确实回收性能啊还是非常不错的啊,否则的话呢,它也不会呢,是不是成为咱们叫张二八的,是不是叫默认的垃圾回收器啊。对吧,诶它的回收性能还是不错的,但是呢,我们也要能看到啊,在一些具体的一些场景当中,比如说我们对这个,呃,系统的这个叫响应时间。诶,我们对这个系统的响应时间呢,比较高的这样的一个项目当中,诶我们希望呢,系统能够较快的呃去做,做到这个我们程序的一个响应啊,不愿意看到呢,过多的一个延迟啊,像咱们前面讲的这个parallel的话呢,它其实主打的是不是叫吞吐量有限对吧?诶适合于我们这个服务器端,但是针对我们这个呃一些响应呢,比较看重的这样的一个场景的话呢,我们用这个parallel呢,实际上就不太合适了,呃因此的话呢,我们在这个1.5这个版本当中还及时的就推出了叫CMS啊这个垃圾回收器,那实际上呢,在1.4的时候呢,已经开始啊张罗这个事情了啊行,那么CMS呢,它这个垃圾收集器呢,主要关心的呢点就是尽可能的缩短垃圾回收,呃,垃圾收集的时候呢,用户现场的一个停顿时间。
02:36
啊,这个并发的话呢,我们说是不是就能够主要来解决这个问题是吧?诶,但是你注意我们说是尽可能的减少啊,而不是说呢,我们把这个stw stop the word这个时间呢给它消除掉,这个是不可能的,任何一个垃圾回收器呢,都会有这个stop the word的这个情况的啊这个大家注意一下,呃,停顿时间呢,或者我们也称为呢,叫低延迟,呃,这个。越适合与用户交互的这个程序呢,这个低延迟是吧,就是这个低延迟这种场景呢,就特别适合呢,跟用户交互的这样一个场景当中,良好的这个响应速度呢,能够提升用户的一个体验啊,像咱们这个平时用手机的时候呢,大家应该明显能感觉到哈,苹果手机跟这个安卓手机。
03:15
啊,仅仅从这个跟用户交互上的话呢,明显能感到是这个感觉到这个iOS这个操作系统呢,实际上是更加流畅一些的,对吧?诶当然这个流畅的话呢,跟我们说,诶是不是垃圾回收器的原因,这个呢,不简简单单是因为这个原因了,更多的还是因为我们这个对于苹果来讲,它的这个底层的这个硬件,包括呢,像CPU的设计,呃,那么软件的操作系统包括呢,它这个APP开发的这个语言,整个呢,这一套全都是,是不是Apple苹果自己家的是吧,所以说它这个兼容性的话呢,就非常的好,它呢也不用考虑过展的过多的这个拓展性。啊,里边呢,就没有过多的这个接口啊,所以它整个这个流畅度啊就非常的好,那安卓的话呢,咱们知道呢,它是一个生态了,涉及到呢里边的各种各样的厂商,包括CPU啊,硬件啊等等都是各家公司的,所以里边呢这个接口会比较多啊,导致呢层层调用啊,显得呢就会这个碎片化更严重一些啊,主要呢,其实是这个原因造成的啊,那么大家现在呢,很多时候买这个苹果手机,除了呢以前的时候啊,你像放到这个三年前,你说买苹果手机的感觉特有范儿是吧,特有面子啊,但是现在的话呢,明显能够看到这个安卓的这个不管是屏幕的质量啊,照相啊等等一些这个待机啊,快充啊是吧,各方面的其实都比这个苹果要好一些,现在呢,自我感觉哈,选择苹果的手机的人呢,嗯,应该主要呢,还是看中的它这个流畅度。
04:33
哎,主要看重这个流畅度啊,OK行,那么下边我们就提到说,在市面上有很大一部分这个Java应用呢,集中在这个互联网的这个网站上,或者呢,基于这个BS系统的一个服务器端上。啊,那么像这类应用的话呢,尤其重视这个服务的一个响应速度,希望呢,这个系统的停顿时间呢,尽可能短一些,给用户呢,带来比较良好的一个交互体验,那这个时候的话,我们这个CMS呢,它就派上用场了,那正好呢符合诶这类人的一个需求。
05:00
OK,那么CMS呢,这个垃圾回收器呢,它采用的算法呢,实际上从那个名字当中呢,就直接暴露出来了,叫标记清除算法。诶大家注意啊,咱们这块呢,是第一个提到了叫标记清除算法,而不是用的标记压缩算法,嗯,那也会呢,提到了叫solve the word一个场景啊这个咱们都了解啊好,下面呢提到说不幸的是啊,咱们这个CMS呢,垃圾回收器呢,它不能够跟我们前边啊1.4中提到这个parallel呢,是配合工作的,只能够呢跟咱们这叫panel或者zero呢,它呢,诶二选一这个咱们在这呢,是不是也说到这个场景了,那当然呢,我们说这个原因的时候呢,就是提到了说这个parallel呢和parallel o包括呢,我们这个叫G1,他们三个的话呢,是用的这个底层垃圾回收器的,这个底层这个垃圾回收用的这个框架跟咱们前边这些呢是不太一样的,所以呢,他们没办法兼容呢去使用。诶,主要是这个原因造成的啊,这个大家注意一下行,嗯,那么后边呢,我们说还会引入叫g first啊,这个J呢,是我们JDK9当中,哎,默认的垃圾回收器了,那G这个出现之前的时候呢,我们这个CMS呢,在刚才提到的这样的一些这个场景当中。
06:08
在这样的一些场景当中啊,它还是非常具有广泛应用性的。这个g first出现之后啊,我们说呃,它呢是兼具这个并行与并发这样的特点的,所以我们主流的其实还都哎用这个叫诶g first了,哎,这个大家稍微注意一下啊,那目前的话呢,我们说还有很多系统呢,诶可以考虑去使用这个CMS,那因为我们呢,现在其实主要讲的是不是这个housewa的虚拟机是吧?那除了这个house虚拟之外呢,我们说还有其他虚拟机,哎,那么他们还可以考虑呢,使用这个CMS,在咱们这个housewa虚拟拟当中呢,他们后边会说在GDK14的时候呢,是不是已经把它干掉了,前面我们也稍微提到过这个事是吧?好,那么接下来的话呢,咱们看一下这个CMS的一个工作原理。这个工作原理啊,相较于咱们前面讲的那些呢,就稍微的复杂一些了,诶就稍微的复杂一些了,那我们看到呢,首先呢,是用户线上去执行,当我们这个内存呢,你发现不足的时候啊,注意这时候呢,我说的这个不足啊,那跟咱们之前那个不足呢,就不太一样了啊一会呢,咱们会强调这个事情啊这个我们开始呢,进行垃圾回收的时候呢,首先呢,经历一个叫初始标记,嗯叫initial mark啊初始标记,然后呢,有一个叫并发标记,这个并发标记呢,就concurrent mark这个标记的时候呢,大家会发现我们就是一个并发执行的。
07:22
嗯,看大家会发现这个用户线程和我们的这个垃圾回收的这个线程是不是同时执行啊,而这个环节的话呢,还是一个叫stop the world一个场景,不过呢,这个时间非常短啊,这个时间呢非常的短暂啊,然后第三个环节呢,就称为呢叫重新标记啊remark,那重新标记的话呢,大家发现呢,是不是也是一个stop the world的一个场景。对吧,诶stop,而且你看它是可以有多个线程同时的进行标记,然后最后一个环节的话呢,仍然是一个并发执行的,那我们叫并发的一个清理,哎,跟我们的用户线上呢,又可以是同时的执行。啊,后边有个重置线程,哎,这个呢,就是在我们核心讲的话呢,可以就哎归结为这样的四个步骤,初始标记,并发标记,重新标记和并发清理,或者叫并发清除,诶都可以。
08:08
好,那么接下来的话呢,咱们就一个一个的来看一看这里边儿的这几个环节。啊,一个一个看这里边的环节,那首先的话呢,这个叫初始标记啊,这个为了咱们讲的时候呢,更清楚一点,这样我把这个图的话呢,咱们给它盯一下啊,诶放到这个上面。好,来看一下这个初始标记啊,就是我们说的这个环节,在这个阶段当中,程序中的所有的这个用户线上啊,都得是stop the word啊,只有我们的垃圾回收线上呢去执行,那这个环节我们做什么事啊?哎,说这个阶段的主要任务啊,仅仅只是是吧,标记出GC roots能直接关联到的对象。你看我们这个时候呢,做的这个事儿啊,非常的少。你像咱们叫并发,咱们叫并发呢,是不是尽量的就是诶刚才提到是不是叫低延迟啊,咱们提到叫低延迟,所以呢,我们这时候先标记的时候啊,只有你垃圾回收线程执行的时候呢,咱们做的事少一点,诶只是呢先诶标记出你能够直接关联到的对象就可以了,一旦标记完成之后呢,咱们就赶紧的结束这个stop,走这个事件。
09:12
这时候呢,我们就进入第二个环节,可以呢,并发的去执行了。所以呢,我们这个环节呢,虽然是STW的,但是呢,它的执行速度呢,非常的快。这个环节执行速度非常快,所以说呢,这个STWSTW,这个时间非常的短暂啊,需要注意行,那第二个环节呢,我们称为呢叫并发标记concurrent mark,那这个阶段的时候呢,咱们从这个jc roots,因为我们上一个阶段这个jc roots呢,是不是已经都确定下来了,那这块呢,就从这个jc roots出发,它这个关联到这个直接对象呢,接着往下再去遍历,遍利整个这个对象图的一个过程。依次呢,往下去延伸啊,针对于我们说,诶可达的对象呢,做一个标记是吧,这样。那么这个过程啊,咱们相对来说耗的这个时间啊,就会更长一些,你像前面呢,我们这个GC roots只是标记了这一层是吧,那接下来呢,层层的往下去递进,这个时间呢,花的肯定要更多一些。
10:06
啊,但是呢,这个环节呢,我们说跟用户限制呢,是同时执行的,是并发的,所以呢这块呢,不涉及到stop the word这个场景,哎,不用担心。不用担心对吧?OK,然后第三个环节的话呢,叫重新标记,这个呢大家应该也能够去理解啊,你想想我们第二个环节呢,是并发标记,就是这时候的用户线程还在执行,那这时候我们这些标记啊,是不是有一些就不是特别的精准呢?对吧?诶,所以呢,我们在第三个环节呢,需要做一个修正修复,这个为了修正并发标记,这个期间因为用户线程呢,继续运行而导致标记产生变动的那一部分对象的一个标记记录,就是我们相当于做了一个重新的修正,那么这个修正的话呢,你就不要再执行用户线程了,你要这时候再一执行那不成了,还得修正没头了,所以呢,我们这时候呢,就要重新标记啊,它这个环节也是一个STW的。
11:01
哎,这个环境也是一个STW的,但是呢,毕竟这个呢是只是做一个修正嘛,所以这块花的时间呢,其实也比较短。哎,也比较短,当然呢,比我们这个初始标记呢,这个时间稍微长一点哈,你看比这个初始标记时间长一点,当然跟这个比的话呢,那就诶更短了,比如这是一秒,这是两秒,这个呢是十秒。能理解吧,当然在这个十秒十秒当中呢,咱们是一个并发的对吧?哎,所以你就不用考虑说这个呢,ITW呢是十秒了。好,然后呢,诶,我们重新标记完之后做了一个修正,下边呢,就是真正的要处理了,所以在这个第四个环节呢,就要con sweep这个环节呢,就是清除掉咱们这个标记当中是垃圾的那些对象,哎把它们呢标记为这个死亡,哎释放这个内存的空间。那就这样一个情况,那这块呢,你注意咱们用的是叫并发的清除,是不是不是叫comp压缩是吧,所以这个时候呢,我们清除完以后呢,内存中实际上是不是会存在一些碎片的问题啊。对吧,哎,会存在这个内存的一个碎片啊,那后续的话呢,实际上我们可以考虑啊,再考虑使用这个压缩算法呢,把它做一个内存的一个呃清理啊,这个是可以的,行呃说由于呢不需要移动这个存活对象,所以这个阶段呢,也是可以跟用户先生呢并发执行的,你看并发执行,所以真正我们涉及到STW的时间呢,只有这个环节和这个环节,而这两个环节呢,实际上是我们这个诶执行的起来的话呢,花的时间最短的,所以呢,诶我使得我们这个STW这个时间呢,整个呢也是比较短的。
12:33
OK行,那这的话呢,咱们就首先呢,把这个诶CMS呢,这个垃圾回收器的一个基本情况,还有它的一个工作原理呢,咱们就诶说清楚了。
我来说两句