00:00
那讲完这个强引用之后啊,咱们下边给大家讲解一下,这个叫软引用,诶软引用呢,我们称为呢叫soft reference,那相较于我们说这个强引用啊,这个软引用呢,就稍微的弱一点啊,是相较于强引用弱一点的这个引用类型,它的主要特点啊,大家如果要是用一句话呢来概括的话呢,就称为叫内存不足啊及回收啊,咱们刚才那会儿呢,在整个介绍四种引用的时候呢,咱们已经说到过了,那下边我们再来看一下这个内部的这个细节信息。说软引用软引用啊,它是用来描述一些还有用,但是呢,又不是必须的对象啊,因为你要是必须的话呢,咱们就直接用这个强引用的,对吧,说只被软引用关联着的这个对象呢,在系统将要发生内存溢出之前,咱们会把这些对象呢,进行一个呃二次回收。啊,二次回收,这就提到叫二次回收,那第一次回收是什么呀。诶,第一次回收,你注意就是指的咱们那些所谓的叫不可达的那些对象,诶或者准确的说呢,应该叫不可触及的对象,能理解吧,诶不可触及的对象就是像我们强引用当中已经没有引用指向了,像咱们刚才那会儿提到的啊,比如说我这儿呢,没有这样的一个操作,哎在这种情况下呢,咱们这个IT2呢,它指向的这个对象呢,就应该被回收是吧?呃,这个呢,你可以理解成就我们说的叫依次回收,咱们现在呢讲的这个软饮也好,包括接下来的这个叫,呃,这个弱引用,还有这个续用也好,他们首先呢,他们都是可答的哈,这个大家要注意,诶,我们刚才讲这个PPT的时候。
01:27
你看在上边这块提到了啊,咱们呢,都是可达的情况啊,都是可达的,就等于这个叫可初级的对吧?诶这个在这种情况下,我们来谈一谈这个回收的意思啊,所以呢,它比强呢,要稍微弱一点嘛。啊,就是当我们这时候呢,再把这个嗯,没有就是不可不可触及的这个对象回收完之后呢,发现这个内存还是不够,这时候我们就要开始对这个软引用呢,呃,可触及的这个软用呢进行动手了,是呢,我得把你们回收一下啊就是这个意思,那如果回收完以后呢,还这个呃,导导导致这个内存呢不够,那这时候你该报这个OM呢,就会报这个OM。
02:05
但这时候大家注意啊,咱们这个报的OM跟咱们这个软用可没有关系。能理解,不就是说咱们这个软语用啊,它是不会导致咱们出现OM的软语用,不会你像我们这个你内存不够的时候呢,你都把我都回收掉了,我我都死光光了是吧,你这个海报内存一出,那你跟我这有毛线关系啊。是这意思吧,诶我们导致这个内存溢出呢,其实诶这个强引用是咱们说的主要的一个原因啊,这个软引用啊,弱引用啊,续用啊,它都不会涉及到这样的问题,OK,就是内存溢出跟非强引用没关系啊,因为你都把我回收掉了,你跟我有啥关系啊,对吧?那么我们这个软引用呢,使用场景是什么呀?我们说通常用来实现内存敏感的叫缓存,比如说这个高速缓存啊,就有使用到这个软引用,那如果说呢,我们有这个空闲的内存了,这时候咱们就保留这个缓存数据,那我们加载呢,运算呢就会更快一些,那如果说,如果说这个内存空间不足的时候呢,那这时候我们把这个缓存数据呢,就给它清理掉啊,不会耗尽,保证呢,我们这个内存呢,就不会被耗尽。
03:07
啊,所以说比较灵活一些啊,那比如说呢,咱们这个my base这个源码当中,它的一些内部类当中,实际上呢,就使用了我们这个叫软引用啊,就使用这个软语用在这呢,我们就不给大家呢去看这个源码了,就啊大家呢下来呢可以去诶查看一下这个底层源码,OK,那么下边也提到说垃圾回收器呢,在某一个时刻决定回收这个软可达对象的时候,或者叫软可触及对象的时候呢,那会清理到这个软引用啊,同时呢,我们也可以考虑呢,把它放在一个引用队列当中,那同这个队列当中,我们依次取出来做一个清除啊这样的一个工作,OK啊下边也提到这个弱饮用啊,说只不过呢,这个Java虚拟机会尽量的让软饮用呢,存活时间稍微长一点。啊,因为这里边儿我们其实呢,做一个总结的话呢,就针对于咱们刚才说的这个叫软引用啊,得用最简洁的来描述,就是当这个诶内存足够时,那内存足够的时候呢,我们说不会是不是回收。
04:02
哎,不会呢,回收软引用的对象是吧。啊然引用的这个,诶可达对象或者叫可触及的对象,那下边呢,就是当内存不够时。那当内存不够的时候呢,我们才会啊回收。哎,这个,哎这个是不会啊,通知到这儿。哎,行,就这样CTRL一下。把这个诶布呢给它去掉,所以它的这个就是看这个内存够不够了,而对于我们这个嗯弱引用来讲,那对这个弱引用来讲呢,跟内存够够没关系,只要你J些的时候呢,我们就都会回收啊就注意这两个点啊行这呢我们就说到这,然后接下来的话呢,我们提到说在这个扎点浪包rap这样一个包下呢,我们有个reference,那soft这个reference这样一个类,我们那会也看了,对吧?诶通过这个类呢,我们去实现这个叫软用这样的一个可达对象。那最核心的代码呢,我是放在这了,比如说呢,我们上面的这个强引用,然后呢,把强用的这个变量呢,我们放在咱们这个new soft reference这个对象的这个行参这块放进去了,这呢其实就相当于创建了一个软引用,但这时候你注意啊,这时候这个软引用我们这个new的对象呢,它呃,既有一个强引用的一个关联,又有一个呃,软引用的一个关联,那我们还需要呢,把咱们这个强引用的这个变量的支撑是no,这个时候呢,我们这个obg对应的这个实体对象,它才只有唯一的一个软引用。
05:27
啊然后呢,你涉及到垃圾回收,内存不够的时候呢,再回收,那这个一定要注意啊,这个操作呢,需要有,你要没有的话呢,这个软饮用呢,它它相当于没起作用,因为呢,我们这是不是有个强影啊,你要内存不够的时候呢,JC也不现实,因为呢,这个有个强影在这撑着呢,是吧?啊就我们说这个天塌下来有个高的呢,来顶着呢,这就那个个高的嘛,那那就不主要来考虑你了,行,那具体呢,咱们可以看这样一个代码啊,大家来体会一下,诶我们先给大家强调的这样的一个行为啊找一下这叫soft reference啊这个代码呢,猛一看好像这个代码量挺大的啊,实际上呢,啊也比较简单啊,每次好像经常都说这些话是吧,对于大家呢,有过Java开发经验的来讲呢,这里边我写的咱们各个章节这些代码呢,都是为了去刻画咱们想描述的这些文字。
06:13
啊,要不呢,咱们讲这个文字的话呢,就有点太枯燥了啊呃,就是想着法呢,我们把这个场景呢给大家构建出来啊这个代码呢,本身呢,其实难度不大,但是呢,你去构建这个代码呢,难度是有的。嗯,OK,那这里边大家看一下,我这呢是呃,声明的一个内部的一个类啊,就是一个普通的一个user类,然后呢,有两个属性。啊,非静态的,然后一个图形方法播到器,OK,比较简单,然后接下来呢,是一个main方法。嗯,一个没方法,我这呢是这样写的哈,嗯,我直接呢就new了一个soft reference啊,这是带泛型的,把我们这个user呢,就直接造进去了。啊,直接造进来,相当于我们现在呢,New的你这个对象它就是一个软引用对吧?啊这个大家注意我们这个操作呢,其实我也可以给他按照咱们刚才PPT的方式,是不是改成几行代码也是OK的呀,能理解不就是好比是这样啊,我声明一个叫USER1啊,你有一个user。
07:03
啊这呢,我们写个一啊这个啊,这是我的这个名字是吧,诶这样子,然后呢,我们再去造,咱刚才说的这叫呃U一个soft reference啊把它CTRLC下拿来,把这个U呢放进去。然后在接下来我把这个UE呢,再制成个no。我这一行代码注意啊,它呢等价于我们下边的这三行代码,能理解吗?哎,上面的这个一行代码等价于哎如下的哎三行代码。就是最终目的呢,我们希望呢,就是你只有一个关于我们这个对象的一个软引用,对吧,那把这个强语呢,一定给它去掉。哎,这个取消啊强应用,哎主要呢,就是这个目的啊,或者呢,大家这样写也可以。啊,也可以行,这个呢,用这个也行,用这个也行啊,然后在接下来的话呢,我们关于这个soft reference里边,因为你放在实体呢,就是我们用的这个对象嘛,诶我们从这个盖的方法呢,就能够获取它内部的这个实例,所以这个时候呢,我们去调这盖的方法是可以拿到这个对象的,那下边这块代码呢,咱们先都给它注释掉,把这个程序呢,我们先跑一下。
08:16
啊,这里边儿我加相应的这个信息了啊,咱们先把这个信息呢,也给它去掉。嗯,在这是吧,哎都删了啊。没问题对吧,诶就是我们这个钙的方法,大家注意我们后边呢,这个关于弱引用,它也有这样一个方法,通过这个钙的方法呢,咱们能获取到你这个封装的这个实体对象,诶这呢,就是掉了我们上边写的这个图损率方法了,对吧?这个非常简单,好然后接下来的话呢,大家注意我这儿呢,有一个叫JC。我做了一个JC操作对吧,那JC操作之后呢,那我们现在想看一下,说此时这个对象呢,还在不在。啊,这个对象还在不在,那咱们用的这个对象,其实它占用的空间呢,是比较小的,咱们如果没有设置这个对空间的话呢,其实这块呢也不会超对吧,那意味着就是我们实现这个这些以后呢,再去看一下在不在呢,其实它还是会在的。
09:12
还是会在的,那我们跑一下。你看我们在执行完这个JC之后呢,你发现它是不是还在啊,因为我们通过这个get方法呢,能够获取到,对吧,或者呢,大家你觉得这个不是特别稳妥的话呢,你可以针对我们这个类,咱们在这进行个设置啊,比如说咱们设置一下这个内存堆空间十兆,这是它的一个初始内存,然后最大的内存也是十兆,OK,现在我们把它加上。没问题是吧,那十兆的空间的话呢,我们这个对空间你再分分新生代老年代啊,放这个对象呢,也是足够的,你看这时候呢,还是在的行,那么在接下来我们这样来处理了,就是当你内存够的时候,咱们说呢,你就不会是去清除我们这个所谓的叫软运用,对吧?那当内存不够的时候呢,我们就要进行清除了,下边呢,我们就来演示这个内存不够的这个场景。
10:01
诶,我们就把这个代码呢打开。诶大家看我们呢,呃,设置这个堆内存呢是十兆,十兆的话呢,诶按咱们默认的情况呢,新生代和老年代的是不是1:2啊1:2,那你出三份这个呢,大概是六点六点多是吧,那这个呢就是三点多,那现在呢,我们造了一个BAT数组,这个数组呢,你看它这个长度呢是七。那我们把它呢,要是放在对空间中的话呢,是不是没有这个足够的空间去放,是这意思吧,1D呢,就是这行代码一定要写完以后呢,我们就会报一个OM,我们把这个意义上呢给它,呃这个这个呃捕捉一下。啊,因为你这是error嘛,所以我这就写成slope了哈,那你这块呢报OM,那我们说呢,你报OM之前是不是我们要把这个软引用这个对象呢,给它诶清除掉啊,那你要是清除掉的话,诶导致呢,咱们如果再次从这个reference里边去获取这个对象是不是就拿不到了呀。诶,你看这个理解是非常的清晰是吧,好,那下边呢,咱们跑一下这个程序。
11:01
嗯,你看我们这个程序呢,执行完了,这呢,是咱们在造这个数组之前还是能获取的,也就是说咱们内存足够的情况下。哎,垃圾回收之后,然后应用这个我们在这写一下啊,这个由于哎堆零堆空间啊,内存足够啊,所以呢,不会回收,哎,咱们这个叫软用在这个,哎柯达对象。OK,这呢,就我们说的这个没有回收的情况,然后当你这块呢,非得造一个字节数组,导致我们这个资源紧张啊,这个呢都不至于紧张了,都直接呢就OM了,那么在这OM之前呢,咱们这个就会把这个re用这个可达对源呢进行回收,呃,异常呢该爆爆了,然后同时的话呢,当我们再试图去获取的时候,那这个时候呢,已经是闹了,哎,这个我们在这写一下啊说由于。哎,或者这样写啊,说在哎报。在OM之前。
12:00
啊,这个我们说JC啊,就是垃圾回收器。啊会哎,这个回收这个软用的可达对象。嗯,可大对象是吧,诶这个呢就很好理解,像这呢,就是我们说的这样一个场景啊,嗯,那么再来一个。再来一个这个比较精准的一个操作哈,什么意思啊,这块呢,其实已经能够演示咱们要说的问题了啊,那我还想呢,给大家再呃演示一个小的例子,嗯,这个例子呢,想说明什么呢?就是呃,我们在这个OM之前的话呢,咱会去回收这个呃让意用,但是呢,并不一定说会报这个OM哈,就是我们这个呃数组咱们造的呢,此时咱们造这个数组不是说资源紧张了,是你这个就是资源就不够啊。哎,让系统认为啊,内存资源这个时候呢,咱们是紧张或者叫不够,现在咱举这个呢,实际上是不够了,那能不能说造一个例子说紧张啊,也就是说呢,能不能说不报这个异常,就是没有出现OM,也有可能会把我们这个软饮用回收掉呢,那其实呢,也是可以的啊,也是可以的,但这时候你就非常的精准了啊,就是我们这时候这个对空间呢,既能够放下我们这个数组,同时的话呢,还还容不下咱们那个user。
13:22
就上面的user。再说一遍啊,既能够放下这个数组,但同时这个推空间,推空间呢,还容不下你这个user,这个是不是就是个技术活了,你像我们造哥这个数组比较这个比较大,直接呢,对空间都盛不下了,那你肯定要把这个挤走了是吧,现在说诶不报这个OM的情况下呢,还能诶这个这个就是既既既不报OM,同时还容不下一个它。诶这样是吧,那这个怎么整啊,这咱们得需要看一下这个内存的具体这个细节了啊,所以我在这块呢,诶这样一下。啊,Print,呃,这个JC,呃,Details,我们来看一下这个,呃,打印一下这个堆内的一个详细信息啊print j c details,好,我点一个OK,呃,目前啊,咱们写的是这个数,呃,现在呢,需要对这个数啊,咱们做一个修正啊,这块我重新的给大家复制一份啊把这个呢,咱们给大家注入掉,行,那咱们说呢,现在是这个七兆的空间呢,是堆空间就乘不下了OM了,咱把这个数呢改的小一点,比如这块我就先是这个一兆的空间,对吧,然后我们先跑一下。
14:27
诶跑一下可以了,你看这时候呢,因为咱们这个内存空间啊,它比较足够是吧,比较充裕,所以说咱们后边呢,经过这个GC之后的话呢,你再放一个数足,诶仍然呢,能够查到我们现在这个软引用这个情况,那现在这个一兆的数据呢,咱们是给它放在这了,其实是是吧,诶其实放在这了,然后下边呢,我们先把这个数据呢给它撑起来,撑起来的话呢,如果说你要是放在这个新生代的话呢,变得大一点,它大不了它就给你往老年代这去放了,那怎么办呢?我们要想要想让它呢接近于这个OM,咱们就想办法把这个老年代呢给它撑起来。哎,老年代呢是7168KB,那这块我们可以这样来写啊,嗯,那这块呢,就是算叫7168了呗。
15:08
7168,然后呢,我们乘以这个1024,它现在已经使用了叫635这个KKB了,那我们这块呢,给大家减一下,嗯,我叫635啊,乘以这个1024是吧,我先这样来写一下啊,1024啊。呃,就是我们想把这个老年代呢给他,呃撑起来或者接近,于是这个撑起来,先看一下这个情况啊,然后我们这时候呢,给它跑起来,因为现在呢,你这个新生代已经放不下了啊,咱们就给它放到老年代了,那放到老年代的话呢,你看这时候呢,是7152,那7152就都放这儿了,放这儿的话呢,你看我们上边,诶这个时候效果已经出来了啊,我们这个时候,嗯,一开始的时候呢,我们在进行这个。呃,After这个JC的时候,诶我们这时候找呢,还能找到,然后呢,当我们再放一个数组的时候,你看我们把这个堆空间是不是撑的就比较大了,呃在这种场景下呢,我们呃由于呃那堆空间的不足了,但是并没有去报这个OM,你看是吧?呃没有报OM的情况下呢,我们说也可能会出现把这个软也用这个可达对来进行个回收。
16:11
啊,这个大家要注意啊,诶不一定咱们说一定是报OM了之前咱们才会回收,就是你内存空间不够的时候呢,咱们就会回收,哎,所以回过来你看这块我写的说当内存不够的时候,这个描述是比较准确的,不一定是OM行,这个呢,咱们就说清楚了。
我来说两句