Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/310.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 理解弱引用_Java_Memory Leaks_Weak References - Fatal编程技术网

Java 理解弱引用

Java 理解弱引用,java,memory-leaks,weak-references,Java,Memory Leaks,Weak References,我相信我终于理解了WeakReference,我想确定我没有弄错 考虑一个Map clientMap,它是名为MyService的Singleton类的private属性,我们使用该类将注册的客户端映射到它们各自的回调 现在考虑下面的代码: // We register a client and it's callback MyService.getInstance().register(client,callback); // .. some code happens .. // At t

我相信我终于理解了WeakReference,我想确定我没有弄错

考虑一个
Map clientMap
,它是名为
MyService
Singleton
类的
private
属性,我们使用该类将注册的客户端映射到它们各自的回调

现在考虑下面的代码:

// We register a client and it's callback
MyService.getInstance().register(client,callback);

// .. some code happens ..

// At this point, we decide client no longer lives anymore
client = null;
到目前为止,即使
client
现在指向
null
clientMap
仍然引用了
client
以前指向的地址,从而导致内存泄漏

  • 我说得对吗
  • 如果问题1是肯定的,那么继续:我们决定,为了防止内存泄漏,我们也应该从客户端映射中删除对象:

    client = null;
    MyService.getInstance().unregister(client); // This methods calls Map#remove(Client)
    
    现在我们已经修复了内存泄漏

  • 我还是对的吗
  • 如果问题2是肯定的:由于一些无法解释的问题,我们无法真正调用
    Map#remove()
    ,因此这就是
    WeakReference
    的用武之地

    通过使用
    Map clientMap
    ,引用计数器不会增加,一旦我们设置
    client=null
    它会自动从
    clientMap

  • 我还是对的吗

  • 是和否。当所有引用(不包括弱引用)都存在时,对象在下次扫描时可用于垃圾收集。在您的情况下,它不会像预期的那样工作,因为映射仍将包含指向nothing的WeakReference的条目,并且映射到指向nothing的WeakReference,我认为在不迭代所有键/值的情况下无法删除该元素

    上一个示例的第二个问题是回调现在也是一个WeakReference,这意味着它可以被垃圾收集,即使它仍在使用中,只要不存在对它的其他引用。听起来不像你想要的

    Client client = ...;
    Callback callback = ...;
    Map< WeakReference< Client >, WeakReference< Callback > > map = ...;
    
    map.put( new WeakReference< Client >( client ), 
             new WeakReference< Callback >( callback ) );
    callback = null;
    // Uh oh, callback can now be collected but client is still connected
    
    Client=。。。;
    回调=。。。;
    Map,WeakReference>Map=。。。;
    映射放置(新WeakReference(客户端),
    新的WeakReference(Callback));
    callback=null;
    //哦,现在可以收集回拨,但客户端仍处于连接状态
    
    最好的解决方案是在不再需要时从所有集合中显式删除元素。这消除了对GC的任何依赖,而您从来都不希望依赖GC,并且集合中没有需要稍后清理的悬空条目

    另一个解决方案是使用一个。这看起来正是您想要的,它将在回收密钥时处理任何悬空条目。它确实有它自己的陷阱。它不能保证这些条目何时被回收,也不能与循环引用一起使用,因为值仍然是通过强引用引用的。这意味着,如果回调保留对其客户机的引用,它将永远不会被回收,因为回调是强引用,而强引用是对客户机的引用,依此类推


    为了澄清为什么WeakHashMap会出现“何时”的问题,WeakHashMap可以随时清理悬空的条目。只要它在没有开发人员干预的情况下完成。这意味着,在不再需要这些值之后,它们仍然可以被强引用。

    这就是为什么存在这些值的原因。不需要做映射使用WeakHashMap怎么样?WeakHashMap听起来很完美,但我不理解这一点:一旦客户端变为null,插入它的WeakReference现在将返回null值。这是否意味着我必须迭代地图的条目才能删除死亡的WeakReference?“WeakHashMap中的条目将在其密钥不再正常使用时自动删除”不,它将由它自己完成WeakHashMap将管理悬挂的条目本身,这意味着您无需做任何事情来删除它们。同样,文档没有指定何时从映射中删除条目。它只是指定在没有开发人员干预的情况下将其删除。这可能意味着GC可以告诉map释放条目,map会在后台线程上清理自己,或者当开发人员访问map时map会清理。WeakReference,这就像说“嘿,我想要一个对X的引用,但我不想让它一直保持活动状态,如果其他代码不再需要它,就扔掉它,忽略我”请注意,“无限内存使用”与“内存泄漏”不同。如果您的地图包含无限数量的对象,但您仍然可以访问地图实例,则这不是泄漏。它可能最终耗尽可用内存,是的,但不会泄漏。