• z.l
    2019-11-27
    看了源码重新理了下思路:
    1. 创建ByteBuf时调用了track0(obj)方法,传入的obj就是创建的ByteBuf对象。
    2. track0(obj)方法内做了2件事
       a. 创建一个弱引用对象,绑定上面传入的ByteBuf对象和一个全局的弱引用队列refQueue。
       b. 把这个弱引用对象加入到另一个全局集合allLeaks里面。
    3. ByteBuf对象用完了,正常情况会调用release()方法回收堆外内存,同时release()方法中调用了弱引用对象DefaultResourceLeak的close()方法,从allLeaks集合里面把这个弱引用对象移除。如果开发者忘记调用release()方法,则allLeaks集合里还会存在这个弱引用对象。
    4. 一段时间后,ByteBuf对象被GC回收,此时会触发一个操作:ByteBuf对象所绑定的弱引用对象被加入到refQueue中。
    5.下一次创建ByteBuf时又调用了track0(obj)方法,把refQueue和allLeaks这俩集合一对比,既存在于refQueue(说明ByteBuf用完了且已经被GC回收),又存在于allLeaks(说明没调用release释放内存),表明存在内存泄漏。
    展开

    作者回复: 嗯,你总结的挺全面的,其实这块很饶人,像你这样分块看挺好!

    
     9
  • zpzeng
    2019-11-29
    老师,针对这个检测有几个问题想不明白,弱引用对象指向的是谁,是堆外内存,还是持有堆外内存的堆内对象?GC的时候,弱引用对象不是应该被回收掉吗,那么弱引用队列 allLeak里还有对象能和refQueue做对比吗?堆外内存的释放是个什么概念,是没有被堆内对象持有,还是有个位置存储内存块的可分配状态?
    我能假设的一个相对合理的解释是:弱引用指向的是堆内对象,GC的时候堆内对象不引用堆外内存,但没有显式的释放,此时这个对象被回收了,然后这个对象的弱引用被记录到refQueue中,然后某个时间出发refQueue 和allLeak的对比,发现有堆外内存没有被释放。但是这样就有“C的时候,弱引用对象不是应该被回收掉吗,那么弱引用队列 allLeak里还有对象能和refQueue做对比吗?” 的问题。
    麻烦老师解答一下
    展开

    作者回复: 这里你抓住几个关键点:
    1 GC的时候,堆内引用不可达了,所以才被回收了,所以错失了主动释放的机会;
    2 弱引用对象的回收就和普通对象一样,所以开始加到list后,假设没有释放,会在list里面,所以有人指向它,所以它不会被回收掉。所以后面refQueue才能拿出对象看看在不在list里面。

    
    
  • 鱼向北游
    2019-11-29
    allleaks为了做快速查找那个应该是个set一类的吧 但是大家都叫他链表

    作者回复: 谢谢提醒,最早是linked list.现在是set.不知道以后变成什么,不同版本都不一样都,以后也不知道变成什么,不过大体思路都是一样的:判断集合里有没有这个对象来判断gc后的对象引用计数有没有到0。

    
    
我们在线,来聊聊吧