00:00
好,同学们,咱们接下来的话呢,讲一讲这个内存泄露的问题,内存泄露的话呢,咱们再讲到MAT这个工具的时候呢,诶说到这个大MP文件啊,也是频频的提到了内存的泄露啊,因为我们说出现OM也好,或者没出现呢,出现频繁的fordc也好啊,我们这块呢,都要关心的说是不是这个内存过小或者内存泄露了,诶所以呢,我们要分析这个大文件对吧?那另外呢,这个内存泄露呢,咱们在讲上篇啊垃圾回收的时候呢,也专门提到了内存泄露与内存溢出啊,那当时的话呢,我们没有给大家过多的举特别多的例子,是吧?啊,因为我们上篇的这个知识容量呢,还整体来讲是比较多的啊。那咱们在这个下篇当中呢,给大家呢再谈一谈这个内存泄露,包括呢,很多同学在实际面试当中经常也会被问到,说你能谈一谈内存溢出和内存泄,呃,内存溢出和内存泄露的关系嘛,对吧?呃,以及呢,你能不能举几个代码的例子说一说啊,这就是内存泄露的情况啊,那么这里呢,我们关于呃,大家的这样的疑虑啊,包括内存泄露的一个案例分析啊,咱们都给大家呢来谈一谈啊,这块呢,把内存泄露这块呢,咱们说清楚啊。
01:06
首先的话呢,关于内存泄露呢,我们先做一个简单的回顾啊,这呢是咱们讲到上篇的时候呢,呃,用到的两个图。用到的两个图,首先呢,说何为内存泄露啊,这点的话呢,大家先要有一个明确的概念啊,别理解错了啊,说到这个可达性分析算法,咱们在上面讲到的说呢,用来判断这个对象呢,是否不再被使用,是否是不再被使用了,那本质上的话呢,就是判断一个对象呢是不是还被引用啊,那么对于这种情况呢,由于代码的实现不同,就会导致很多内存泄露的问题。啊,让这个GM误以为呢还在使用,但实际上呢,我们已经不用了,对吧?哎,那造成了内存一个泄露问题。啊,这个应该很清楚啊,但这块我们再强调两个概念,这个第一个概念呢,说呃是否啊被使用啊,或者叫是否还被使用。第二个概念呢,我们说,哎,是否还被需要。
02:03
哎,是否还被需要是吧,哎,这样两个词大家来判断就行,比如说是否还被使用呢,那我我们这如果说是一个是。啊,就相当于现在还使用着呢啊第二呢,是否还需要被使用呢。还还被需要啊,或者要被需要使用,还被需要吗?如果这时候也是一个是,那这是不是内存泄露呢。显然不是对吧,你比如我们上面这个图当中,那我们这个,呃,这是目前的一个对象的一个引用关系啊,大家可以理解成呢,这就是一个强引用,然后的话呢,嗯,这个我们进行JC操作的话呢,这块区域的这些对象还就应该被使用的,对吧?所以呢,他们就不应该是被JC的啊,这就不应该被JC的,所以这种两个如果都是是的话呢,那它不是一个内存泄露问题啊,那说是否还被使用呢?是是否还需要被使用呢?哎,这个呢,如果我们说的是一个否的话。
03:00
那这就有问题了,说现在还没用着,但是我实际上已经不需要用了,那就比如说咱们,哎,就比如咱们这块看到的。诶这个啊,这块这个区域的数据一样是吧,那这个数据的话呢,我们其实已经不再用了,但是呢,由于这个指针呢没有去掉,导致呢,我们这块数据呢,是不是没办法通过这个GC进行回收啊啊那其实这块呢,就是内存的泄露问题。嗯,这个还被使用吗?被使用了这块有指针是吧,是否还需要被使用了,我不需要了啊,这块导致这些回收不了,所以呢,它是内存泄露啊那呃,那还有什么情况呢?说是否还被使用,那如果说啊否。是否还需要被使用,它都否了,那不都没有了吗?那这块是不是就不用问下边一个问题了,哎,是这样子的哈,行,那就通过这两个词的话呢,大家就能判断出来它是不是一个内存泄露问题啊就可以了,好,下边呢,我们再来看一下关于这个内存泄露的一个理解啊,诶这呢,也是咱们上篇中提到过的,一个是严格意义上的,一个是这个宽泛意义上的。严格上来讲说只有对象不再被程序用到了,哎,是不是说的就是这个事儿啊,但是呢,JC又不能回收它们啊,相当于我们现在还占用着呢,指标它指向了呢,是吧?哎,这呢才叫内存的泄露。
04:12
啊,程序不用了,但是JZ呢,又回收不了,这叫内存泄露。啊,那宽泛意义上来说什么意思呢?就是我们在实际情况当中啊,可能会有一些不太好的一些编码习惯啊,一些实践疏忽导致呢,呃,有些对象的这个生命周期啊,变得特别长,以至于呢,跟我们GM的一个生命周期都是一样子的,就始终呢回收不了,最终呢,呃,积累过多导致OM了,那我们也可以理解成宽泛意义上的一个内存泄露。什么意思啊,哎,大家看下边这个例子啊。这里边儿的话呢,我们有XY和ABC4个,呃,五个引用,那X呢引用了YX呢引用了ABC,首先呢,针对XY来说,X的生命周期比较长,Y的生命周期呢,本身人家要被使用的这个范围呢,其实比较短。对吧,哎,就这么长,但是呢,由于我们这个X引用呢,指向了Y,那所以呢,X在它的这个生命周期范围内,尤其是我们指的就是这段时间之内啊。
05:08
哎,这段时间之内,这个由于X呢指向了Y,所以呢,这个Y呢,它就不能被回收了啊,因为有引用指向你,它就是一个可达的对吧,那这个X呢,可能通过某一个jc root呢就指向它了,它又指向了Y呢,所以Y呢回收不了,所以呢,在这段时间之内呢,如果我们这个内存呢,诶不足了,需要进行这个GC的时候,实际上Y呢就回收不,那么从这个意义上来讲啊,这个我们把这个Y呢也看作是一个内存泄漏问题。啊,也是内存泄漏问题,那同样的,如果X呢,还指向了ABC,那如果ABC的这个本身的生命周期应该是比较短的,但是呢,由于X比较长的一个生命周期调用了他们仨了,导致他们仨也不能够及时的被啊JC掉,那这呢也称为是内存泄露啊。行,那关于他们二者之间的关系呢,啊,应该比较好理解了啊,比较好理解啊,这儿呢,相当于又给大家举了个例子啊,就是内存泄露呢,就是咱们啊就是大家呢,如果你面试的时候呢,跟面试官讲,一方面呢,你可以讲的这个理论性强一点是吧?呃,另外一方面呢,你也可以稍微的形象一点啊,就是比如说我们申请了这个内存。
06:12
这个用完了不释放啊,就现在呢有啊1024兆的这个内存分配了512这个521。啊,521512是吧。写错了啊。嗯,这是1024哈,这个分配了512的这个内存呢,一直这个不回收,那么可以使用的呢,是不是就只剩下这个,剩下那一半的512了是吧?那仿佛呢,就是泄露掉了一半啊,有一半因为你不会收就用不了嘛,那只能用这一半啊,就这种情况啊,那对于这一部分的内存就是相当于是一个泄露啊,那就类似于啊,这个老百姓通俗的讲了一句这个词叫占着茅坑不拉屎是吧?啊非常的通俗是吧?哎,那这呢就是你不操作,但是呢,你又站着,这就是一个泄露。啊,就这意思,那什么叫内存溢出呢?啊,就申请内存的时候,没有足够的内存可以用了,这时候呢就会溢出啊,通俗一点讲,比如说一个厕所呢,有三个坑,然后有两个占有两个呢,占着这个坑啊,不走啊,这就是泄露的嘛,那剩下一个坑,这一个坑呢能够使用,所以他的压力就很大啊,那现在呢,突然来了俩人,俩人都要进去,那这时候不够了,所以呢,就出现内存的一个泄露问题啊,内存的一个溢出问题了。
07:20
啊就是哎,我们现在想用两个坑,结果呢,没有不够,只有一个坑啊,没有两个坑共使用了,所以就是内存的溢出。他们俩的二者的关系呢,就是内存泄漏多了就会导致溢出啊,这个应该很好理解是吧,不用多说,下面呢,关于泄露的一个分类哈,这里边分成了按照其实就是频率的问题啊,经常发生,偶然发生啊,一次性的还有隐食泄漏。什么叫经常发生啊,就是当我每次执行这个代码的时候呢,都会出现泄露。啊,每次执行的话呢,都会出现泄漏,这呢就称为呢叫经常发生啊,那这个呢,我们是不是一定要去规避这样的问题,对吧?啊这是它啊,哎,这个呢叫做偶然发生。
08:01
哎,偶然发生在某些特定的情况下呢,才会发生啊,比如说呢,我们关于这个资源的一个关闭数据库连接啊,或者我们这个用IO流呢,操作这个来磁盘或者网络中的数据啊,哎,那这个时候呢,哎没有出现异常,就是如果我们把这个资源关闭的这个操作哈。哎,正常来讲,咱们说都应该放在这个是不是finally当中,对吧?哎放在finally当中,它就一定会被执行,但是呢,你要是没有加这个finally啊,没出现异常,那当然了,还会执行close,但如果呢,出现异常了,哎,它就这个这个Rose就走了是吧?哎假设呢,你也不是一个拆开啊,整个这个呢,就抛出异常出去了,那这时候呢,导致我们这个资源呢,就没有关闭啊,这呢就属于在你出现异常的情况下呢,就没有呃执行资源关闭就偶然发生的情况啊。还有一种叫一次性的,就是发生内存泄露的方法呢,只会执行一次啊,那这种呢,就是嗯,还好一点是吧?啊,因为它就只泄露那一块啊呃,你只要这个空间别太大就行啊。嗯,再下一个呢,叫做隐视泄露啊,隐示泄露就是一直占着内存不释放,直到呢执行结束,严格上来讲呢,这个其实不算泄露啊,因为最终也释放了,但是呢,由于执行时间过长,也会导致呢内存的一个耗尽啊,这个呢,其实就有点像咱们刚才说的那个是不是宽泛意义上的这样的一个泄露了是吧。
09:18
啊这呢其实也算啊,那我们也看到是内存的泄露啊行,那这呢,就是我们关于这个内存泄露呢,呃,就又进行了一个呃,熟悉啊又熟悉了,熟悉然后下边的话呢,诶,我们会给大家列举八种情况啊,这个呢是需要大家在面试当中啊,你跟面试官呢,是可以去交流的,包括这里边呢,也会有很多的这个代码啊。行,那我们先这个概念性,先有一个理解。
我来说两句