00:00
那讲完可达性分析之后啊,咱们说一个知识点,这个叫对象的finalization机制啊,就是关于我们说对象呢,在进行回收之前啊,涉及到一个方法的调用啊来我们看一下对吧,Java语言提供了叫对象终止的机制,来允许开发人员呢提供对呃,提供这个对象被销毁之前自定义的一个处理逻辑。哎,就是相当于是我们在这个对象呢,销毁之前呢,我们还可以加入一些具体的这个逻辑代码,诶就是这样的一个意思,那这个功能呢,通过哪一个方法呢去实现呢,这里边提到了一个叫finalize这个方法。啊,你看这块提到说当你垃当垃圾回收器啊,发现没有引用指向一个对象的时候啊,没有引用指向的对象,我们说呢,它实际上呢,就是一个垃圾对吧?那那吃一个垃圾呢,我们垃圾回收器呢,要回收,它在回收之前咱们呢,就会调用这个对象的叫finalize这样一个方法。能明白吧,是吧,反这个方法,那这个方法的话呢,我们说任何一个对象呢,都有可能会调用这个方法,那言外之意呢,这个方法呢,就是一个通用的方法,那意味呢,这个方法呢,就会定义在啊我们说这个根赋类当中啊这呢,我们就找到这个叫object这个类对吧?哎,我们这块呢写一下。
01:07
啊,找一下我们这个叫object,那进来以后呢,我们在object当中就找到了这样一个方法叫做。啊finalize啊这呢关于它的一个说明说,靠啊,它呢被调用通过这个这个garbage collector就是垃圾回收器作用在一个对象上说,当垃圾回收决定呢,没有任何引用这个指向咱们当前对象的时候呢,垃圾回收器呢,就会调用这个方法。你要说的非常明确对吧?哎,所以说呢,这个方法的调用呢,就是诶,在我们垃圾回收器回收这个对象之前进行的一个调用。啊,这是这样一个描述,然后呢,这个方法本身啊,这块关了,那咱们从这也能看啊,啊ctrl shift t,咱们找一下这个叫object。嗯,Object在这打开,那那这呢,我们就看到这个叫泛life这个方法,这个方法本身呢,没有加final,它是一个protected了,那就意味着我们实际上是不是可以重启这个叫翻life这个方法。
02:01
没问题对吧,还没有加final,我们可以没有加final,也没有是呃private这样的声明呢,我们就可以呢,进行一个重写,OK,那可以重写,那重写的话呢,我们一般都这个在方法体里边写哪些操作呢?啊这呢说通常呢,是用于在这个对象呢被回收之前啊,进行这个资源的一个释放。来进行资源的释放,比如说呢,关闭文件啊,关闭套节字,关闭数据库连接,那这样的一些情况,相当于呢,进行一个资源的释放,或者是一些清理的一些工作,那说到这块的话呢,大家应该能够这个类比的去想到我们说的这叫sol,比如说对吧。那这个so类的话呢,我们说它也有一个方法叫做destroy啊,是属于它生命周期的一个方法,就是当我们这个so呢,在被销毁的时候呢,呃,你可以呢,需要进行哪些操作,你可以在这个destroy里边呢,进行一个重写啊,这是其一,那如果说大家呢,做安卓的话呢,安卓我们说有四大组件,那其中一个非常重要组件呢,叫做activity对吧?那这个activity呢,就是咱们对应的手机的具体这个页面,这一个页面呢,那如果我们用这个Java语言来进行开发的话呢,咱们说叫万事万物皆对象这一个页面,其实呢,我们就可以理解成就是一个叫activity,那当我们这个页面呢,在销毁的时候,比如说我们点一下这个返回键,那把这个页面呢就销毁掉了,那么在销毁的时候呢?它对应的一个生命周期方法叫做on destroy。
03:17
啊,TRY是吧,那当你这个activity这个界面呢,在销毁的时候呢,我们可以呢,要调用这个方法,在这个方法里边我们可以做什么事呢?比如对你当前这个页面中的一些数据呢,进行一个持久化的保存,我们就可以去重写这个ONG串一个方法,包括了一些资源的关闭啊也是可以的。哎,跟我们这里边要讲的这个finalize这个方法呢,是有一定的类似关系啊好接着往下看,下面提到说永远不要主动的去调用某个对象的叫finalize这个方法。首先说呢,就是咱们看到这个object当中这个finalize方法呢,其实你看它是没有任何方法体的,对吧,那如果说你在没有重写的情况下呢,你去调这个finalize本身呢,也没啥意义,因为里边也没东西。
04:00
能理解对吧?好,那如果说我们重写了啊,你重写了finalize这个方法以后啊,咱们说也不建议呢,你去哎去调用咱们这个,诶finalize这个方法就主动的咱们去调,注意啊,这样咱们不要主动去调,那应该交给呢,咱们叫垃圾回收机制啊,我们刚才在API里边不也看到了,说应该交给咱们这个垃圾回收器是吧?诶垃圾回收器呢,他会主动的去调用咱们这个叫。哎,这个finalize这个方法的啊,涉及到那个线程呢,叫做finalizer啊finalize这个线程,那为什么不让主动调呢,这块呢,提到了三个原因,第一个呢,说final这个方法呢,它可能会导致对象的一个复活啊,这个呢,一会儿呢,咱们就有这样一个演示啊,下一个说finalize这个方法呢,在执行的时候呢,它这个执行时间呢,是没有保障的,它完全呢由JC这个线程来决定,在极端情况下呢,若不发生JC3大这个方法呢,就没有机会执行了。咱们刚才提到说,当这个垃圾回收器去回收我们当前这个对象的时候呢,我们才会去调用这个方法,那如果说没有去调用这个GC,那就导致我们这个方法呢,就没有去做执行。
05:06
对吧,哎,它就像是一个,呃,这个其实也不完全像哈,就是我们讲Switch case的时候,有个叫default,就是一个咱们说叫做备胎一样啊,他不是说什么情况下都能执行啊,就这块呢,咱们更多的时候呢,这个方法就是啊,在我们这个垃圾回收器回收这个当前这个对象的时候,他主动的来调这个翻来的方法,咱们不要主动,咱们不要呢,自己呢去通过对象去调他。啊,他的这个优先级呢,也比较低啊,优先级比较低,即使呢,你自己主动去调理方法呢,它也不能够保证说马上就要执行,诶这个要注意下一个说一个糟糕的finalize这个方法呢,它会严重的影响JC的一个性能。那这呢,主要还是涉及到你自己重写了,对吧,那我们重写这个翻代的方法里边,我们要做一些事情,那如果说你这个执行的代码呢,呃,由于执行的这个比较缓慢啊,或者说呢,这个嗯,你这是一个死循环,你想想我们这个垃圾回收金呢,本身要回收这个对象呢,在回收之前呢,要调理方法,一调这方法呢,是一个死循环,那你想想我们这个GC的性能呢,是不是严重受影响?
06:08
此循环的话呢,就是非常严重了哈,那你要是执行速度很慢的话呢,这边也会拖慢整个垃圾回收的一个性能。诶这呢,就是我们提到这个点,OK,那其实这块呢,不光是说咱们不要主动去调,而且呢,还说明了就是你自己重启的时候呢,也要注意一些问题,对吧,你也要注意些问题,就是我们可以在里边实现那个对象的复活,然后呢,你要写的这个翻比较糟糕的话呢,对我们JC呢是有影响的,然后呢,提到了就是说呃,你想让他马上执行这个事儿呢,是不能保证的,因为呢,它是在一个呃,Finalize一个优先级比较低的一个线程当中去调用的。啊,你直接呢去调查,他不能保证马上执行。啊,就是基于这样的一个情况,OK,然后下一点呢,就提到这个翻类这个方法呢,它跟咱们C加加里边提到叫C库函数呢比较像,但是呢本质上又不同,因为我们说Java呢,是一个自动的内存管理机制,这个大家了解一下就行,嗯,那咱们比较重点呢,是给大家要说明下边这个问题啊,就前面这个内容呢,咱们一说大家可能就能明白,下边这个说由于这个finalize这个方法的存在呢,咱们说虚拟机中这个对象啊,一般存在三种可能的状态。
07:11
那如果说面试问到你了,说我们要回收一个垃圾的话呢,我们这个在回收之前会不会有一些行为的调用。啊,我们可能这个关于这个对象呢,有几种状态这块呢,你要提到它可能会有三种状态。哎,三种状态的出现呢,就是由于咱们这个finally这个方法,好,我们下边来看一下。嗯,就是这里边儿提到的这三种状态说,如果从所有的根基点都无法访问到某个对象,这显然呢,是不是就是提到我们叫可达性分析对吧?可达性分析里边呢,我们使用的叫GC roots。啊,就是根节点嘛,那我们看一下能不能这个访问到某一个对象,是否可达,说如法,如果无法访问到,那其实就是不可达了,那说明了当前这个对象已经不能再被使用了,说白了就是垃圾呗,那就需要被回收。啊,但是需要被回收,事实上呢,说这个对象也并非非死不可,就跟咱们古代呢,看那个,嗯,那个那个男主角是吧,已经上了这个刑场了,然后呢,马上就被这个这个叫什么刽子手,然后就要砍头了,那正常的话呢,我们说,哎也并不是非死不可,很多时候呢,我们看到这个戏剧的一幕呢,就是啊,刀下留人是吧,哎,结果呢,没死成,那就成了一个可复活的状态了。
08:23
只能说呢,他快在那儿呢,就有可能会被杀掉,但也有可能呢,杀不掉,所以呢,也并不是非死不可,只能说呢,他们现在处于一种叫死的,叫什么缓刑的一种阶段。就有可能会会会减刑是吧,有可能死不了,咱们法律上呢,也有这种死缓对吧,后来呢,就从这个无期徒刑啊死缓啊这块,又这个判判30年是吧,30年有时候表现又好,改成十年,会有这样的一个这个情形对吧?行,那下边说说一个无法触及的对象,有可能在某一个条件下呀,复活自己,那如果这样的话呢,诶对它的回收就是不合理的了。
09:01
那那这三种状态大家看理解一下啊,第一个呢,叫做可触及的状态。可初级状态说白了就是人家就不是垃圾对吧?这是咱们是通识的,通俗的来讲述一个对象的三种状态,就是第一种情况就不是垃圾,因为我们通过这个根节点啊,咱们能够直接间接的最后访问到这个对象了,那说明它就是可触及的,它就不是垃圾啊,这是第一种情况,那么下边这两种情况大家看。如果呢,我们去从根节点来访问的时候,发现不可到达这个对象,不可到达的时候呢,按说我们就要被回收了,但是回收之前呢,咱们要调这个叫finalize这个方法。对吧,还咱调这个方法那行,那么这样什么叫可复活的呢?就是对象的所有引用啊都被释放了,说白了就是你是不可达的,在不可达的情况下呢,咱们这个对象有可能在finalize当中呢复活。一会儿咱们给大家演示啊,有可能会复活,这是一种情况,这呢就是叫可复活的状态,然后再一个呢,就叫不可触及的状态,那说白了就是就得死。
10:01
咱们说呢,并不是Facebook这个呢,就是他又从这个刑场上又被救下来了,就没死成就复活了,那下边这个就真死了,说呢,对象的finalize呢,被调用,并且呢,没有复活。Fair被调用了,并且呢,没有复活,没有复活呢,那他就进入这个叫不可触及的状态,那就真得该死了。哎,不可触及的对象呢,是不可能再被复活的,你说诶,那能不能我们再重新调一下finalize,然后就复活了,不行,因为呢,Finalize这个方法呢,只能够被调用一次。这个大家要记住它。啊,刚才呢,咱们提到一点说finalize咱们不要主动的调,这个大家记住对吧?第二点呢,就是这个findize的方法呢,属于我们垃圾回收器呢,它自动的来调,但自动调的时候呢,它只能够被调用一次,也就是说呢啊刀下留人啊,只能是说一次。刀下留人啊,救了救了那就复活了,没救成没救成那就死了,就不可出击了啊,那就已经都杀了是吧?那你说在刀下留人都已经死了,你还刀下留啥人呢?
11:02
对吧,这是一个,再一个呢,就是刀下留人啊,救了救了以后呢,说呃,下次又要被杀了,又要被杀的时候,注意这时候就不能在刀下留人了,因为就只能掉一次啊。说的是不是有点绕啊啊,就是就是你只能喊一次刀下留人啊,能救就救了,救不了就死了,就这意思,你问救,救了救了以后下次要再死怎么办?下次再死那就不能倒下留人,那就该死,就得死啊,就是这个意思。嗯,就这个意思啊行,那下边说以上三种,以上这个三种状态是由于finalize这个存在呢,这个导致呢,对象呢,有三种情况。啊,只有呢是不可触及的,他才是真的要被回收掉了,哎,这个意思,那具体这个过程咱们再来磨叽一下。据这个过程啊,需要大家去理解,就是我们说呢,把这个对象回收啊,发现呢,这个还还没那么简单对吧?里边呢,还有一个事儿,就是这个finalize这个方法说呢,呃,如果我们想判断一个对象呢,叫obj a判断它呢是否可回收,咱们说至少要经历两次标记过程。
12:03
看两次标接过程,首先的话呢,我们看下这obj,它到这个jc root呢,有没有这个引用链,咱们前面提到过引用链的问题,对吧,就是我们这有没有这样的链存在,那如果让你这个引用链呢,是可以达到它的,那就说明你是个可达对象。那可拉对象呢?你就不应该去销毁人家?对吧,啊不应该销毁,那如果说没有饮用料,那就说明呢,我们初步判定啊,他这时候应该要被回收了,当然诶,这时候我们就要定行第一次标记,这时候所谓的第一次标记呢,我们说当前这个对象它有可能被复活,也有可能呢,哎,就就要被回收,就真的死掉了,就是这时候还定不了,只能说呢,第一次标记的时候呢,它肯定不是一个可初级的吧,有可能是这个或者是这个。理解吧。对吧,哎,这个意思好,那么接下来我们要进行筛选啊,判断这个对象呢,有没有必要呢,去执行这个finalize这个方法,诶有没有必要执行啥意思呢?那这个说如果这个对象啊,没有重写这个final。
13:01
或者呢,你这个finalize呢,已经被调用过了。那这个时候呢,我们说他就认为没有必要再去执行了,直接呢就死了。能行吧,你看第一个呢,说没有重启,那为什么没有重写也算呢,大家看到咱们额不债当中,你要没重写的话呢,里边啥也没有,也就是说呢,你这里边呢,是不可能出现自救的,就啥呀,你里边方案题也没东西,所以说我都懒得去执行你这个final light了,对吧?哎,就不掉了。啊,这是一个意思。嗯,这个我看看啊,再CTRL。推一下行,那第二的话呢,就是说你这个翻袋的方法已经被调换过了,因为咱们刚才提到过,说你只能被调一次,说已经刀下留人说过了,那现在不能再说了啊,那就得死,所以呢,就是不可出击。嗯,这样,然后下一个说,如果对象这个obj重写了这个对象所属的类是吧,你重写了这个翻带的方法,而且呢,你还没掉过,诶这时候呢,咱们就要被掉了。啊,就要被调用了,哎,那这个OBGA呢,它就会被插入到叫FQ啊这样的一个队列当中。
14:04
诶,到到这个队列当中,然后呢,由虚拟级自动创建的一个优先级比较低的啊,叫finalizer这个线程,去触发咱们这个翻的方法,这就相当于我们现在要唯一的调用这次翻的方法了。哎,这提到一个线程叫做finalize。对吧,行,那说到这咱们先停一停啊,让大家呢看一下,比如呢,我们打开咱这个之前写的这个程序,就是关于我们这个去测试这个叫应用技术算法的时候是吧?哎,我们在最后这块,比如咱们加一个这个具体的代码,哎,比如我这让这个程序呢,做一个sleep。那时间呢,比较长一点,好拆开这一下行,那我现在把这个程序跑起来,那显然的话呢,它不会马上呢,就把这个进程呢给终止掉了,对吧?OK,然后接下来的话呢,咱们在这个这VVM当中打开看一眼。Reference count DC行,然后在这呢有个叫线程,那线程打开以后呢,大家会发现这呢,就是咱们当前这个程序当中跑到线程,比如这呢,是不是主线程。
15:03
啊,都在执行的对吧,那其中呢,你会发现呢,有一个这个现场叫finalize。哎,就这样个现场。啊,这个线程,那这个线程是个等待状态是吧,这个线程呢,就是我们所说的这个优先级比较低的。啊,由这些垃圾回收器呢,啊,它提供的一个啊,用于呢,咱们进行啊finalize这个方法调用的这样的一个,哎线程。嗯,这不是跟咱们前面刚才说的,说咱们不要主动的去调这个翻带方法是不是也是呃匹配的对吧?嗯,主动调的话呢,也不能保证马上执行,因为呢,它是由这个优先级比较低的一个线程来跑的啊,这个大家注意一下行啊这呢我把这个程序就停下来了啊。行,这是这个事儿,那由这个优先级比较低的这个线程呢,帮我们去调这个final方法,行,那下边就调呗,啊finalize这个方法的调用,诶是我们这个对象呢,能够逃脱死亡的最后机会。啊,稍后呢,这个JC会对这个队列当中的这个对象来进行第二次标记,第二次标记啊,说如果这oga在这个final方法啊,与引用链上的任何一个对象建立了联系啊,这大家注意,那么在第二次标记的时候呢,OV就会被移出即将回收的集合,说白了就是这个时候如果你发生了这个行为。
16:17
那么我们这个当前OBDA这个对象呢,你就是可复活的。那你就是可复活的了,那怎么叫可复呢?就是你跟现有的这个引用链你给搭上关系了。那你给答案关系了。啊,这个再举一个场景,就好比是这个以前战争的时候啊,这个很多,嗯,不管是中国了哈,国外也是一样,那这个呢,就是马上要进行一个这个这个敌人就过来了,然后怎么办呢?说这时候呢,大家可以去坐船是吧,去到另外一个城市,但是你要坐船的话呢,这个船的这个座位毕竟是有限的啊,你必须得托关系啊,托关系呢,你能够弄到一张船票,那你就上去了,你要是托不到关系呢,你是不是就得死啊。哎,那我们这里边所谓的说这是这个大陆,这是你这个,呃,这是地面是吧,这是你这个船,然后呢,你托关系呢,你能托上关系了,所谓的关系呢,就是你跟这里边比如这些人呢认识啊,人家呢,给你一张船票,你就进去了,诶那这呢,就是我们说人家都是可触及的那些对象,诶你能跟人家搭上边,直接或间接的跟这个JC是吧,如此搭上边了,哎,那这时候呢,你就是一个可复活的了啊,那你就能升,那你要是没有搭上边,那你就就得等死啊,敌人那块过来看挂掉了。
17:26
啊,这样啊。行。嗯,这呢是我们说这个你是一个可复活的啊,说之后呢,对象啊会就是之后啊之之后呢,对象会再次出现没有引用存在的情况,就你这块呢,跟引用链呢,当然关系上没死,但是你要之后呢,又出现没有这个引用链了,把的引用链又断开了,那么在这种情况下呢,泛赖的方法呢,就不会再掉了,因为咱们说它只会被掉一次是吧,那你只能使用一次啊,那这个时候的话呢,那你就直接呢就不可出击了,就挂了。啊,这种,嗯,那要说呢,你在进行第二次标记的时候,就是我们要去调这个。
18:02
Final这个方法的时候呢,发现你跟这个影链上的这个对象没有建联系,没有建立联系,当然你更是这个叫什么不可触及的了呗。OK吧?哎,别这个有点绕是吧,哎,也就是说呢,咱们所谓的第一次标记呢,指的是没有跟这个GC root呢,诶有这个引用链的关系,那第二次标记呢,是针对我们finalize这个方法的一个调用。哎,针对于他来说的。啊,针对他来说的行,那么关于这个文字描述呢,咱们就说到这儿。
我来说两句