00:00
那么关于咱们说这个Li top这一章呢,最后啊,实际上这是一个补充信息,诶大家呢,了解一下就可以了,就是后边呢,咱们会讲这个具体的垃圾回收器,那其中呢,现在我们JTK当中默认的一个垃圾回收器呢,是做J是叫做这个j first啊叫j first,那这个j first垃圾回收器当中啊,关于这个string呢,它有一个叫驱重的操作,哎,这个呢,大家关注一下啊,那关于我们这个g first它的官方的一个描述呢,这块我们有一个相应的说明啊,这对应的是我们这个GP192,它解决的就是我们在g first这个垃圾回收器当中,呃,去除我们这个string的重复操作这样的一个情况啊,这呢就是我已经打开的这样的一个情况。诶这块呢,有相应的描述,关于他的动机,动机是吧?哎动机是什么,他的这个预期的这个收益是什么样子的,哎这块呢,都有这个描述,大家呢,可以直接呢来这块看一看,或者的话呢,你要觉得里边有一些信息呢,不太这个可读性差一些的话呢,你翻译成这个中文呢,大家看一看也行,那整体上的话呢,应该是翻译的还可以是吧,翻译的还可以行,那这块我们就不来看这个文档了,咱直接呢在这儿给大家呢做一个介绍。
01:03
哎,在这给大家做个介绍,那首先呢,咱们需要说明一个点,就这里边所谓的这个去虫操作指的是什么意思。啊,是指的是我们字符串常量池吗?对吧,你看我这写的是string驱虫,我没说string字符串常量池的驱虫,因为呢,我们说这个字符串常量池当中本身呢,是不是就不存在这个重复的数据啊。能理解这意思吧,本身就不存在这个重复的数据,那我们这呢,其实主要呢,想说明的是这样的一个场景啊,比如我在这块写一下,简单写一下啊,我这块呢,许拟有一个这个叫STR1,然后我们是new一个string,比如说我这呢就叫一个hello。这样子对吧,那我把这个代码呢,我再复制一遍。嗯,再执行一次,这个是它对吧,那咱们应该很清楚的能够画出来当前一个程序的一个内存结构图,这呢是在一个main方法中,那我们这相应的这就是一个站,这呢是我们妹的这样的一个战帧局部变量表里边一个呢叫S1啊,一个呢叫做S2行,我就暂时呢这样来放。
02:00
嗯,但是这样来放行,那么对应的我们是这个,诶对空间里边我们用了俩对象,这是一个对象,这是一个对象,一个呢是这个S1的指向的它,一个是S2指向的它,然后他们两个呢,除了这里边有这个hello之外呢,另外呢,在这个常量池里边,我们说还维护了一个哈,对吧。行,那么这时候大家一定要注意,我们现在呢想强调的你这个呃去重操作呢,是不是一定指的不是这个常量池啊,因为常量池本身呢,就存在的就一份儿,所以无所谓驱重,那咱们现在想说的这个驱重操呢,实际上指的是这个这个位置,那这个位置呢,它其实底层呢用的,我们在这里边会发现它是不是用的那个叫VALUE6啊,咱们在这个GT8当中说这个VALUE6是一个叉型的,对吧?哎,这也是个叉型的一个数组行,咱们现在呢,这个g first当中想强调这个string驱中操作,注意是指的是去重它俩。因为呢,你这俩本质上来讲呢,放的都是hello,说能不能呢,比如说SSE创建完以后,这哥们呢,诶跟已有的这个字符串呢,去比较发现呢,它已经是有也叫hello的这样对象了,那我这块的话能不能考虑说诶你这个就别新造一个对象了,你这个S2这个指针呢,诶你也指向它,当然这个呢,你要想这样去操作的话呢,是不是也得保证是我们有一个叫呃叫什么呀,这个叫不可变的一个特性是吧?诶你这样的指向的话呢,这个如果这个数据变了,你这个就呃不能不能跟着变啊,这个S2的话呢,比如我们这个value叫hello,回头你这里边那个数据改成别的了,然后这个S2的话呢,那孩子也叫hello。
03:21
啊,这个大家要注意一下。这个要注意一下行,就是我们现在指的这个去中操作啊,是指的是去我们这个,哎,你底层new的这个叉形数组的,哎,它的这个重复的操作,而不是常量池的。啊,长安市本身也没有什么重复的,让你可以去取对吧?行,先明确这个问题,然后呢,我们看下这个背景说明,实际上呢,这个背景说明呢,就是来自于我从这里边抠出来的,诶,它下边的这些描述,嗯,在上边儿,其实就在这儿对吧?看其实在这啊行,那这儿呢,我觉得可读性呢更好一点,大家呢,直接来看我们这个文字描述是吧?对,很多的这个Java应用程序啊,有大的呢,有小的,咱们做这个测试结果呢,是这样子的,在这个堆空间当中存活的数据集合中发现呢,有25%呢,都是string的对象。
04:07
哎,我发现呢,命这个比例呢,还是挺高的。哎,你看这个数据呢,对我们前面讲的这个知识点呢,是不是也有一定的启发作用,就是咱们在这个GD8的时候呢,用的是这个差型数组啊,那后边的话呢,我们改成这个叫bad数组了啊,你看一下这个内存空间中中这个堆的这个数据,诶string的数据呢,还是挺多的啊,那我们要做这样一个调整的话呢,显然是不是能节省很多的这个内存空间,对吧?啊,因为内存中咱不是当时也说了说这个,呃,放这个拉丁稳的,或者那个阿斯玛那种识别的,呃,确实还挺多的,那没有必要用叉了,直接用个bet就行,要你用叉浪费一半空间是吧。好,下面啊说这个堆存活数据集合里边啊,重复的这个string啊,你发现呢,你看这是25%,然后这块呢,就13.6%,这一层呢,就27%啊接近一半,就这里边有接近一半呢,它都是一个重复数据啊行,然后这个string对象的一个平均长度啊,是45啊,还不短呢,比咱们预想的是不是比你那个预想的感觉是不是要长一些啊,这是一个平均长度哈,就是有可能存在比它长很多的,也有可能很多呢,比它短很多的啊平均起来呢是四十五行,这呢是一个背景说明,然后下边呢,说大规模的障va应用,它的一个瓶颈呢,就在于内存。
05:17
你像我们希望这个性能提升,那你尽量的减少JC,尽量的减少这个,呃,垃圾回收啊,减少这个内存的溢出情况,对吧?啊,那你要想减少内存溢出的话呢,就是频繁的J些,那频繁这些呢,性能就会低啊,这总之呢,还是由于受到我们这个内存的一个瓶颈的限制啊,说这个测试表明说这些测试的,呃,这些类型的应用里边,刚才我们说到这个情况了,25%呢,都是论的对象。啊,差不多有一半是重复的,就是按照我们这个equals呢做比较,它是个除,或者呢,就是按照这个string1.inten跟我们这个string2.inten,然后之后呢,它俩等等的话呢,还是个主,咱们昨天呢,是不是讲过那个叫if and only if是吧?嗯,行,那这个堆上的存活存在的这个重复的这个词钝对象必然是一种内存的浪费,从咱们这个Java层面呢,只要你是重复的这个数据啊,咱们多少都会认为是个浪费,对吧?那就看你专门的怎么去优化这些重复的数据了。
06:13
这个项目呢,在咱们这个g first垃圾回收器当中,实现叫自动的持续的对重复的string呢,进行一个去重,避免呢内存浪费,那它具体怎么去做的呢?这块呢,我写出来了具体的一些步骤。那这个步骤让大家了解一下就行。说白了啊,就是对于咱们堆上你存活的这个死string对象呢,每一个要访问的这个对象,咱们都会去判断一下它是不是要考虑被驱重,那如果要是是的话呢,咱就把这个对象呢,放到一个队列当中,那这个队列呢,就是我们后边呢要执行的一个队列,把它呢做一个删除,删除以后呢,你再去引用你,诶跟你一样的那个是吧,就是怎么就把你去重了,因为你跟某一个论对象一样了,你去引用那个已有的那个对象。对吧,这样子,然后使用一个high table呢,咱们来记录所有被string对象呢,引用的一个不重复的一个插询速度。
07:01
啊,然后呢,要去去中的时候呢,我们就查这个high table里边有没有跟它一模一样的,如果要有的话呢,那你就是要被去中的,你要没有那就诶放进来。咱们涉及到去重的问题呢,是不是更多的用的都是像哈奇map呀,哈奇table啊,对吧,这样的结结构,哎,咱们涉及到底层那个哈算法效率更高嘛,对吧,所以从面试当中呢,咱们说哈奇map面试的频率极高,因为我们在很多的场景下呢,都会用到它。行,那如果要是存在的话呢,这个我们就把它干掉了,释放原来的这个空间对吧?那如果说要插找失败了,就把它放下来啊,这个刚才上面也提到这个情况了,这呢就是一个驱动操作啊,那具体这个命令行选项这块的话呢,我们说要想呃开启这个这first当中这个string的驱动操作呢,你需要使用这样一个指令,因为默认情况下呢,它是不开启的,你也可以呢,通过下边这两个指令呢,我们去打印一下驱重的一个统计信息啊和呢这个这个年龄的这个死string对象,哎,被认为是驱中候选对象,达到这样的一个4s hold就一个阈值的话呢,我们就认为它是一个驱中的候选对象,行,这个我就不给大家演示了,整个呢,大家做一个了解就行,你就知道呢,诶现在呢,我们还有一些新的思路,就是说呢,诶来把堆空间中你用的那个差形数组重复的那个数据呢,也给它干掉,对吧?诶这就可以了。
08:16
行,那至此的话呢,咱们关于这个string呢,咱们就告一段落,这里边呢,应该算说的比较清澈清清楚一些,然后呢,主要是为了解决大家开发当中一个呢,使这个使用这个词的频率比较高,再者呢,其实重点呢,大家想一想,我们要说的实际上就还是这个叫int的一个使用,对吧,这个大家要重点关注一下。OK啊。
我来说两句