00:00
呃,下边的话呢,我这又举了个例子啊,通过这些例子的话呢,我们想这个复习一下,咱们前面这个内容,就是说呢,我们这个在呃方法当中声明了一些变量啊,我们称为呢叫局部变量,对吧?那这些局部变量呢,我们是不是能够进行垃圾回收的时候呢,把这些对象呢进行回收呢,这呢,我们通过这个显示的调C0.jc这样一个行为,咱们来看一看这个内存的一个变化情况啊,是这样子的行,首先呢,我们来对这个代码进行一个分析,我在这个local啊variable jc当中呢,我们写了这样的五个方法,哎,写了五个方法,然后先看第一个啊第一个这里边呢,我们就生明一个bad形的一个数组,这呢一共是有十兆。嗯,十兆这样的一个大小没问题对吧?行,然后这块我们这个system点对接一下,然后在下面的第二个方法的话呢,我们还是这个十兆,但是这块呢,我们把这个buffer呢,呃,引用呢,随后呢,给它制成个no,再去GC的时候,我们知道它对应的这个对空间的这个对象呢,就已经没有引用指象了,属于不可达的了,我们就要给它回收掉是吧?上面这个的话呢,要回收buffer呢,是不是不太行啊。
01:00
对吧,这个理论呢,咱们都清楚,一会儿咱们通过代码来看一下,然后第三个这个情况呢,我们是在这个方法内部呢,有一个呃叫什么呀,代码块,对吧?这个代码块里边声明的这个变量,我们再通过新GC,我们看看能不能回收,再下个呢,我们这块,诶额外又多定一个变量,诶定义变量有什么影响呢,咱们也看一看,然后再接着呢,是你看第五个方法,我们第五个方法里边呢,先掉了第一个方法,然后呢,我们再进行一次JC看看这样的一个行为。是吧,看下这个行为好,然后呢,下边这个没方法呢,就是我们一个方法一个方法的去调,哎是这样子的,那调的过程当中,我们想看一下这个内存空间的一个占用情况,所以此时的话呢,我们关于这个local variable啊,咱在这个ID的这个位置,嗯,先确保我们先找到咱当前这个程序在这个位置呢,我给大家加个参数啊,这个参数呢,咱们前面大家应该都比较熟悉了,咱们也用过好多次了啊print j CD tas OK,那行这呢我们就写完了,写完以后呢,我们这块apply啊,OK,这都在这个1.8的环境下,我们去执行,首先的话呢,我们先来调第一个local variable jc啊,先来调咱们这个第一个方法,调第一个方法跑一下。
02:07
那这时候呢,大家应该清楚,就是咱们这个buffer啊,如果我们调GC的话呢,是不是应该回收不了啊。对吧,哎,应该回收不了的,行,你看上面呢,我们出现了这个叫哎for GC的行为,这个呢,就是由我们这个CJC呢,它触发的,在这个之前的话呢,先进行过一次,就是在我们for这次之前,是不是先要进行一次这个新生代的一个垃圾回收,对吧?行,那前面这个叫样generation,这个young generation呢,就我们说新生代啊呢,其实就我们后边要讲的一个,呃,Powerline这样一个垃圾回收器了,咱们下一章呢,呃,说完以后呢,咱到时候呢,再给大家讲讲这个这些的这个日志分析。啊,这些这个日志分析行,嗯,OK,那咱们来看一下啊,就是我们首先呢,是有一个新生代的一个情况,然后这呢是新生代的一个初始的一个内存,然后我们回收之后呢,内存这么多,这时候你会发现呢,这个大小实际上是不是跟我们这个十兆的空间的大小是一致的呀。
03:00
没问题是吧,相当于呢,我们这时候呢,进行一个young GC之后呢,这个新生代的这个对象呢,并没有给我们回收掉啊,并未回收掉,然后当我们进行一个for GC的时候呢,它现在你看把新生代中的这个对象呢,是不是整个给它归零了,相当于新生代呢就不放了,但是呢,把这个数据呢,你看是不是放到我们这个老年代里边了啊,说白了就是我们这个buffer这个对象仍然没有进行回收,哎,所以呢,这个就没回收掉,OK啊,本身呢,你看我们也不应该回收对吧?OK,行,然后呢,我们再看这个第二个方法。来跑一下。可以了,那么第二个方法跟我们第一个方法的区别是什么呢?第二个方法当中,咱们把这个buffer呢称和no,那理论上来讲呢,就是它呢,呃,这个要回收的时候呢,我们对空间中这个对象已经没有引用了,其实呢,这个空间就可以被回收,对吧?好大家来看一下,那我们这个样这些的时候,你看这个空间呢,直接就降成这个776K了,这时候呢,是不是已经不足我们这个十兆的一个大小了。对吧,已经不足这个十兆大小了,哎,这呢还涉及到其他的一些数据,所以说我们也占有一定的空间,OK,那呃,包括你在进行这个for这C的时候呢,新生代呢,从776呢直接降成零,然后老年代呢,从2.6,从8K呢到到637K,就是有些数据呢,相当于是就从这个新生代呢,直接调到我们这个老年代了,哎,但是你这时候你发现呢,这个空间肯定不足我们这个十兆的大小,所以说呢,对于我们第二个方法来讲呢,我们这个buff伏对应的这个实体呢,已经被回收掉了。
04:23
OK,能理解对吧?好,接着我们来看第三个。第三个的话呢,我们是这样写的,这呢是一个代码块,那这个代码块,然后呢,这个操作大家呢,如果去执行,可能跟你自己理解呢,就不太一样了,大家觉得我们此时这个buffer呢,会被回收掉空间吗?啊,我想很多同学应该都会打错,那错误的答案是什么呢?呃,会回收啊,因为很多人呢,从理论上分析说我们当前的这个呃数据是不是作用域呢,就是在我们这个大括号内的,对吧?然后你出来大括号之后呢,我们再进行JC时候就应该回收了,那事实上是这样子的吗?诶我们发现看一下,那我们在进行这个样JC的时候呢,你发现我们这个空间呢,是不是仍然占据了这个十兆的一个空间,相当相当于呢,就是我们没有回收掉对吧?然后当我们在行这个for这C的时候呢,这个空间呢,在新生代里边降成零了,然后这个数据呢,但是你存到这个老年代里了,说白了就是我们当前这个空间呢,是不是说没有给释放掉啊。
05:22
因为你看放到了年代了,对吧,那这个事儿该怎么去理解呢。啊,很多同学可能这个事儿呢,理解不是特别好啊,那这个理解的话,大家可以看我们这个叫杰拉lab。来接,然后针对咱们这个第三个这个方法,诶对吧,第三这个方法,然后咱们看下这个叫,嗯,先看下这个叫。看看这吧。嗯,这个呢,是不是叫局变量表对吧?那这个局部变量表里边呢,你看这呢,写了个Z次,这个Z呢,咱们这个之前给大家也强调过,这个局部变量表里边,对于这种非静态的方法来说,它呢局部变量表呢,第一个索引位置,它放的是不是就是这次对象对吧?诶,它就是这个Z对象,但是我们当前这个呃方法当中,它这个局部变量表里边这个长度是多少呢。
06:05
哎,这个我们看一下。嗯,看在哪描述在。在这块描述的,你看在这描述的就是说我们当前这个local variable3这个方法,你看它的最大的一个局部变量表的长度呢,这写的是个二,这写的是二,当然你在这块看到的说怎么就只有一个Z呢,这呢是你这个索引为零的位置,那么索引为一的那个位置是谁呢?实际上是不是就是我们这个buff呀。对吧,诶实际上就是我们这个buffer,那也就是呢,我们这个buffer呢,其实它占用过那个一但我们进行回收的时候呢,其实啊,它还占用着呢,所以就没有给我们去做一个垃圾回收啊,没有进行个垃圾回收啊,这个大家注意一下,那么呃,怎么就能回收了,你看我下边这个写法就回收了,我在这个程序出完之后呢,我又写了一个这样的操作,哎,由于呢,你这个B已经超出了你的作用欲了,我在定义这个value的时候,此时这个value呢,就会占据咱们刚才看到的就是你的索引唯一的那个slot那个槽。
07:03
那那个槽的那个位置了,那由于你占用了那个位置了,所以导致你上边这个buffer占用的这个槽呢,就没有你指向的这个对向的这个引用了,哎,所以我们就可以回收了,来看一看,我们分析一下是不是这样那一回事啊,我们把这个改成这个四跑一下。嗯,好,大家看那这个四的话呢,你看我们这个新生代的话呢,从这个空间是不是直接降到的连十兆都不足了,不足十兆,然后进行这个for这些的时候呢,新生代直接归零,然后老年代呢,诶涨了一下,但是这时候你也会发现呢,我们这个空间是不是也根本乘不下我们十兆的这个数据,对吧?言外G呢,就是我们第四个这个方法的话呢,诶它呢,诶就已经把我们这个字节数组呢给回收掉了。那我们如果看一下它这个自检码这个结构的话呢,大家会发现这样的一个特点,嗯,在这我们code这块呢,点开它,然后看一下诶。诶点这是吧,看下这我们这个字节数组,呃,这个方法它的这个局部变量表的一个长度呢,还是二啊是没有变的,当然这时候呢,你注意一下我们这个零呢,就是这次这个一呢,一开始的时候呢,是我们这个buffer,但是呢,随后呢,它会用我们这个Y6呢,是不是替换掉你这个buffer了,由于替换了,所以导致我们这个引用不存在,所以呢,导致你这个对空间的这个数据呢,是不是就被我们J掉了。
08:24
哎,这个大家注意啊,是有这样个区别,比较难的呢,也是我们这个三跟四啊,这个注意。好,那么接下来我们再看下边这样一个程序,这个程序呢,我们直接调叫local variable j c1调了一下这个一,这个方法一呢,我们那会已经调过了啊,直接调的这一,当时呢,我们这个buffer呢是没有被回收的,但是呢,如果这个方法执行完以后,我们再去调用JC的话呢,大家应该能理解,就是你这个,诶,Local variable j c1这个方法中的那个buff是不是就已经不用了,我把这个改成十和五。跑一下。好来我们看这个场景,那这时候呢,因为我们在这个呃五当中,你调了这个一,调一的时候呢,我们有过一个CJC,就是这样的一组操作,这样一组操作当中跟我们刚才那会看到的一样,诶咱们这个buff呢,在方法一当中并没有给他销毁掉,你看这个是加上零,然后这个就放到这了,这呢是咱们这个一当中,这个刚才已经看过了,对吧?然后呢,这呢是咱们对应的这个第五个这个方法中的这个c.JC这个时候呢,你看新生代这块呢,直接就归零啊,直接归零,然后呢,我们老年代这里边放这个数据,然后后边你结束了的时候呢,咱把这个老年代中的这个数据,你看这不是一开始呢就这么大吗?
09:36
哎,从这个数据呢,这不直接就保留下来是吧?哎,然后呢,我们直接降成了661,这个显然不足10K,也就是说呢,我们这个五这个方法呢,调用之后,哎,你这个一当中的那个八号呢,是不是就被回收掉了呀。OK吧,是吧,你看这边是从这么多讲上这么多对吧?行,那那这呢,我们就说清楚了,咱们想要描述的问题,诶通过呢,咱们这块手动的去调用这个JC这样一个操作呢,咱们来给大家演示一下,就是前面呢,我们说到的哪些对象呢,它就不用了,我们就要回收了啊,是可以回收的啊,他们是不可达的了,这个呢,我们就进行了一个强化。
10:11
哎,大家呢,也可以熟悉一下,下来呢,你自己呢,把这个代码跑一跑,看一看,OK,那我们就说到这儿。
我来说两句