00:00
好,那刚才呢,我们是说清楚了,这个叫gram,那接下来的话呢,我们说一下这个叫thread overw啊说一下这个thad它呢是用来展示咱们当前这个线程的一个概述情况啊,概述情况比如说呢,我们可以去查看当前这个进程当中,哎,我们所有的这个Java的线程他们的一个情况啊,以及呢,还可以查看当前这个线程当中啊,我们说线程是不是都对应的一个独立的一个站,对吧?那么这个站内部的存储的一个一个的战帧里边保存的就是局无变量啊,那我们还可以查看当前这个thread里边的这个局无变量的一些信息。啊,这呢就是我们这个thread over啊,它的一个作用,那我们讲它的一个目的呢,还是为了我们进行这个内存泄露分析使用的啊这个大家注意整个咱们这个大文件呢,分析它都是为了呃找这个内存泄露的这个信息,好那回过来,那针对于我们这里边这个ah pro或者说这个B呢h pro文件啊,选一个都行啊,比如说就A吧,大家点这个小齿轮一样的这个操作啊这个呢,就是关于我们这个TH的这个呃,Overview。
01:07
那这里呢,一共显示出来咱们当前这个文件当中啊,是有六个线程对吧,那分别对应的就是我们这六个,然后呢,那第一个呢,就是我们这个主线程啊,这个妹线程啊行,那其他的这些呢,其实主要都是一些守护线程了,那针对我们这个妹线程呢,大家可以点开这个下拉的这个这个小箭头是吧?诶点开啊这里边呢,提到了说我们这个这个主线程当中,你看这里涉及到一个方法叫做sleep方法,那咱们这个程序的话呢,大家也能看到,嗯,我们有一个执行时间比较长的一个方法,就是这个sleep对吧,还有一个他嗯,OK,然后再回过来。呃,下边呢,就是我们这个main方法啊,这个main方法在执行的时候呢,诶,这里边你看有这个叫local的标识,这个local呢,代表的就是我们当前这个线程当中的局部变量啊,这个大家注意一下,这就是局部变量的问题,那这个变量的话呢,它所代表的这个,呃,有可能是对象啊,当然也可能是这个基本数类型哈,哎,通常我们都说这个对象啊,这个内存泄露的话呢,你说只是基本数据类型,当然也有可能是吧啊,一般的基本数据类型都封装在相应的对象里了啊,那我们就呃可以去怀疑这些对象呢,是不是会存在泄露的问题啊好,那这里边呢,指出来的第一个string类型的这个数组呢,其实就是我们这个main方法的行参。
02:24
哎,没方法的一个形态呢,是一个数组对吧?啊,这是一个,那另外一个呢,就是我们有一个内部的局部变量叫做list啊,就是我们下边这个啊,是一个a list这个类型的啊,这是它具体的这个,呃,这个内存地址是吧?然后再点开的话呢,关于这个a list啊,它的一个类型是a list啊然后呢,这块还有它这个呃,是系统的一个类是吧?然后接下来的话呢,关于这个叫element data。那我们大家都学习过这个release了,它内部呢,装数据呢,实际上用的还是个数组,这个数组的名字就叫做data啊,再往下拉,诶这块呢,大家就能看到当前I data它的类型,以及它内部存储的这些数据啊,这么多是吧?啊,那里边存储的就是我们说一个一个的啊picture啊,一个一个的picture对象,那这个picture的话呢,诶,就是它对应这个内存中的一个地址,在这块呢,诶也都有所显示啊呃。
03:15
那我们读取这个线程中的这个数据的目的是什么呢?就是为了去分析呢,说哪些有可能会有这个泄露的一个问题啊,呃,比如说咱们刚才在这个overview这块呢,这个咱们是不是有一个叫呃立此tax就是它的一个分析报告是吧?好,那我们比如说点一下这个分析报告,那这里边儿呢,大家就能看到他怀疑呢,呃,有这个泄漏问题的这个这个情况还跟我们在下面一个说明说呢,你当前这个线程啊,这个线程呢是呃。地址是在这儿啊,对应的是这个main线程啊,其这其实也说了,那你看这个呢,是不是末尾是CA0,那大家回过来你跟那个匹配一下。啊,是不是就是我们说的这个线程啊,没线程叫CA0啊是吧,就它啊说你这个线程啊。
04:00
尼克线程呢,它里边保存的这个局部变量啊,总共这个大小呢,占据了97.9%这样的一个空间大小啊,可见的话呢,就是呃,当然这里边儿并不是说我们这个内存马上就满了哈,而是说呢,在现有有的对象当中啊,它占据到这么多啊,比例非常的高,比例非常的高,呃,那么接下来再进行分析呢,是由于你这个里边呢,有一个这个结构哈,叫object类型的一个数组啊,这个数组是被它它所加载的是吧?诶它呢,占据了就是97.9%。啊,说的就是它啊,那这个的数组呢,其实就是我们刚才在这里看到的,是不是就这个数组啊。啊,21079是吧,哎,就说的这个数组哈,行,那这里边呢,已经给我们指出来了一个,你可能存在这个泄露的问题,当然呢,呃,这个真实情况呢,我们说这个怎么叫内存泄漏啊,一会儿呢,我们讲到下边内容的时候呢,咱们再给大家谈一谈这个内存泄漏,咱们再讲上品的时候呢,其实提到过这呢,我们再深入的去说一说啊,还有这个狭义和广义上的一个说法,那我们这里边呢,所谓的这个泄露。
05:04
诶大家注意啊,我们这里边呢,所谓的泄露呢,你可以理解成就本身呢,可能我们这些对象呢,没有必要生命周期那么长,但是呢,你这里边儿呢,呃,由于比如说啊这个我们外层呢,有一个生命周期比较长的一个对象去引用它了,导致我们这个生命周期没有这么长的对象呢,始终不能被回收,那这儿呢,咱们也认为它是一个泄露。我再说一遍啊,再说一遍,如果呢,我们有一个生命周期比较长的一个对象啊,比如是个A,然后这呢,有一个生命周期相对比较短的一个对象呢,是这个B,那正常来讲,这个B比如说除了这个它的作用力之外呢,就该被GC回收了,但是由于你这个A呢,始终引用了这个B,导致这个B呢,是不是不能够被回收啊啊那这时候呢,我们就把这种情况,哎,针对B呢,也认为是一个内存的泄露。这呢就是算是这种广义上的一个泄露啊,当然呢,你随着这个A的被这个这个GC掉的时候呢,是不是这个B也就会被GC是吧?哎,它并不是说严格讲这个BGC不了啊,只不过呢,他这个GC的时机啊,没有必要那么久啊,所以这也算是个泄露啊,那这里边呢,就指出了我们当前这个对象呢,你这个占占用的就比较多,哎,我们就要怀疑呢,他的生命周期本身可能没必要这么长啊,其实就算一个泄露问题,大家呢,可以诶针对刚才那个概述的情况,来这里边去找啊,那具体到这儿picture的话呢,诶你看大家点这个右键。
06:18
这里边呢,有一个比较重要的操作呢,就是list objects,哎里边你看大家有两个选项哈,哎,这个比如咱们在在这来点吧,点那个list啊,哎,在这块的话呢,我们看一下这个list,这个list呢,它有两个选项,其实每一个结构都有啊,一个呢叫withoutgoing reference,就是我们呃,这个出去它会引用哪些这个相关的一些引用,这个呢是有哪些对象呢,又引用过来的啊对应的一个呢,叫做出引用,一个呢叫做入引用啊就这样的行为,好,那比如说这里边呢,我们针对这个list,我这块点一下without going references啊点一下。啊,就独立的又给我们列举出来了一个这个项目是吧,然后针对这个release呢,大家再打开,其实跟刚才我们在里边看是一样的,哎,这个呈现的其实其实也不一定一样哈,也不一定一样,这个呢,主要想呈现的就是说,哎,咱们这个list啊,由它呢发散出去,它到底都引用过谁。
07:11
诶诶重画一下啊,这呢,比如说就这个list,哎,它发散出去呢,引用过这个了啊,这个引用这个了啊这个呢,发散出去引用这个了啊,这个引用这个了啊,甚至这个还引用这个是吧?哎这个呢,就叫做outgoing这个references啊相当于呢,就是由我们这个risk呢,我们能找到它的一个是不是outgoing的一个引用链啊。对吧,诶能找这个饮料啊,那么也有可能,比如说我们这个对象呢,按说呢,它就应该是要被J析掉了,但是我们这个往外走的时候呢,就找到它了,找到它以后呢,我们还可以去点这个对象,比如说点右键啊,就像刚才比如在这个位置,我们可以再去看看说谁都引用它了。对吧,谁都引用它了啊,那比如说刚才我们说的这个list引用它了,它又引用它了,哎,那list完的时候它就应该消失掉了,但是现在呢,List是一个局部变量,恰好呢有一个,哎,比如说static的一个变量也用它了。
08:00
是吧,导致呢,这个对象就不能被回收了,那我们就要看一看这个指针是不是有必要存在。对吧,那那如果你发现没有必要,那我们就要把它呢改一改是吧,那你可以把它改成是一个像呃弱引用的一个方式也行啊发现呢就回收是吧。哎,那就好比是我们针对这个picture呢,咱们再去找它的这个incoming,我看看到底谁都引用它了。啊,就这样的问题啊,在咱们这里边呢,发现哎哟只有这个哎a release里边这个数组去引用它了啊那这呢,咱们就啊说啊那那问题不大是吧?哎,如果呢,这时候你大大家发现啊说我们这个picture啊,这个注意听这个注意听啊如果呢,大家发现这个picture的话呢,它下边引用除了你这个object类型数组之外呢,还有一个别的。那这时候呢,我们就要担心了啊,就要担心了,为什么讲呢?因为呢,你看我们这个代码当中这个a release呢,它其实生命周期挺短的,对吧,它生命力挺短的,只要这个main线程呢,呃,结束之后啊,那其实这个对象呢,就会被回收,那以这个对象,这个对象呢,是是不是呃,这个指向咱们这个picture的唯一的一个引用啊。
09:06
好了,所以说呢,我们只要是这个类子呢,诶它挂掉了,那我们这个picture呢,其实也就会跟着挂掉,诶恰好呢,它的生命周期呢,也不长对吧?啊也不长啊,但是咱们这个程序呢,是造出来的,我这块整了个外处了,实际情况呢,咱们不可能是外处,对吧?啊,就是它有可能会执行完,那正常的这个内存呢,也就被回收掉了,可能就没事儿啊,但是哈,但是如果呢,你这里边还有一个生命周期比较长的一个静态变量引用了这个picture了。啊,明明人家这个release呢,就能够清早销毁了,Picture又跟着销毁了,但是你现在的一个静态的变量,再引用了这个picture,导致了静态变量呢,因为是随着呃,咱们这个当前这个进程的结束,它才会结束的,是吧?啊那这时候呢,是不是使得我们上面这个对象呢,导致就始终不能被回收,那它呢,就会存在一个泄露。啊,那修改方式呢,大家你就,诶你要说必须要引用,那你把这个picture对它的这个引用呢,改成是一个弱引用啊就可以了。能理解吧?
10:01
啊,那刚才呢,相当于就是我们基于这个现程的一个概览,这个角度呢,给大家说了一下,我们这个内存泄露,诶里边比较好用的两个工具啊,基于这两个工具呢,我们去做一些呃信息的一些挖掘啊就是呃MAT呢,它能给我们提供的就是这数据,那我们需要呢,通过这些数据呢,有一双慧眼是吧?当然这里边也依赖于大家的一些经验,哎,我这个饼图呢,因为比较简单了哈,当你面对比较丰富的这种饼图结构的时候呢,诶,大家就需要依照你的这个经验呢,然后去里边去分析去找看看呢,相应的一些结构,是不是你真的希望它是一个强引用。啊就可以了,好,这呢是我们说的这个现成的一个概述啊。啊,以及呢,你看咱们通过刚才这个讲解,是把这两个事儿是不是也给大家说清楚了,OK啊行。
我来说两句