引用那些事

2022-05-06 15:36:51 浏览数 (2)

普通对象

普通对象在标记为垃圾时。会把他添加到一个队列中,然后唤醒一个专门用于调用finazlly的damen守护线程去掉用队列里面对象的finazlly函数。

下一次垃圾回收时如果还在队列中则直接释放这个对象的内存空间。如果finazlly中更改了这个对象的引用关系即他被别人引用了那么这时候就不会释放它了,不过下一次再发生gc时不把他添加队列里了直接进行清除

ps:所以finazlly方法更像是一次死亡前的讣告和binder的死亡监听很像。

在binder的死亡监听中可以进行再次启动或绑定服务,finazlly方法也是只要让别的存活的对象引用了它那么就可以不被回收

根据上面得知finalzy函数是有一个专门的线程调用它并且这个damen线程是虚拟机runtine启动start时候进行的无法干预这个线程的运行

虚引用

所以还是用虚引用比较好,使用者知道指定引用队列也可以进行自己指定线程去执行实际对象清理后的回收操作。

也就是:虚引用主要用来跟踪对象被垃圾回收器回收的活动。虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列 (ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之 关联的引用队列中。

案例

也就是leekcanry所做的事情创建虚引用来引用acticity,当引用activity对象被回收的时候将会放到指定的引用队列中(用户定义)。一段时间后(在leek中指的是系统idle的时候因为这个时候会回收不在引用的activity如果这时候引用队列还存在的话则表示内存泄露了)

ondestory时先放到队列1中在用一个虚引用和队列2来持有activity对象代表该activity销毁之后系统idle的时候会回收activity。

注册一个idle回调,在这个里面去检查队列2中是否有activity如果有代表没有泄露因为内存回收了。如果没有代表进行一次手动gc再看队列中还有没有activity,没有被回收就算是发生内存泄漏

0 人点赞