【问题标题】:AS3: Would this cause a memory leak?AS3:这会导致内存泄漏吗?
【发布时间】:2012-06-14 13:45:19
【问题描述】:
public class MyButton extends Sprite 
{     
   public function MyButton(defaultHandler:Function)     
   {     
      addEventListener(MouseEvent.CLICK, defaultHandler);     
   } 
}

//主类

var myButton:MyButton =new MyButton(someFunction);
addChild(myButton)

removeChild(myButton);
myButton = null;

IE 我在构建时从内部向我的 Button 类添加了一个匿名 mouseclick 事件处理函数,而不是在将它从舞台上移除并清空时专门移除它。

这个对象是否适合垃圾收集器,这不会导致内存泄漏吗?或者因为事件监听器只引用了一个本身被删除的对象,它也会被删除???

【问题讨论】:

    标签: actionscript-3 memory garbage-collection


    【解决方案1】:

    Button 实例上的事件侦听器将阻止它被垃圾回收,除非您专门删除了侦听器,或者表明侦听器将是弱引用。

    addEventListener(MouseEvent.CLICK, defaultHandler, false, 0, true);
    

    最后一个参数true,传递给参数useWeakReference。来自docs

    useWeakReference:Boolean (default = false) — 确定是否 对听众的引用是强的还是弱的。强参考( default) 防止您的侦听器被垃圾收集。一个弱者 参考没有。

    【讨论】:

    • 当设置监听器为弱时,移除它的责任转移到垃圾收集器。你永远不应该相信 GC,因为它大多是随机的,所以可能需要一段时间。弱侦听器适用于不负责清理自己代码的懒惰开发人员。唯一的例外可能是舞台上的事件监听器,但您应该始终自己移除监听器。
    • 同意@MarkKnol,我总是明确删除它们。话虽如此,这不是 OP 所要求的。
    • 我发现了这个,虽然场景略有不同,但有类似的问题:stackoverflow.com/questions/8471578/… 有一个引号:“事件侦听器不会自动从内存中删除,因为垃圾收集器会只要调度对象存在,就不会移除监听器(除非 useWeakReference 参数设置为 true)。” - 所以根据这个,如果监听器引用的对象不再存在,它不应该持续存在并且不应该导致泄漏 - 任何人都可以确认这一点吗?
    【解决方案2】:

    虽然@sberry 回答中的观点完全正确,但请仔细看看在这种情况下哪些对象相互引用。

    如果主类在应用程序的整个生命周期内都存在,则没有内存泄漏

    主类有一个对其实例化的按钮类的引用。

    按钮类有一个对主类的引用,来自事件处理函数。

    主类取消其对按钮的引用。

    此时,不再有对按钮的引用。按钮可以并将被垃圾回收。

    如果主类在应用程序的整个生命周期中确实存在,那么没有问题。如果主类以某种方式消失了,但其中一个按钮对象仍然存在那么你有内存泄漏(按钮保持对 main 的引用,并且 main 不能被垃圾收集)。

    PS:我并不是反对在使用弱引用时删除事件侦听器,我尽可能自己做这两种做法:)

    【讨论】:

    • 是的,这就是我所指的,如果对象本身不再存在,那么理论上它的事件监听器也不应该存在。 - 谁能证实这一点?
    • Here is an article from Adobe 支持我所说的。垃圾收集以两种方式工作:引用计数(快速),然后“标记和扫描”捕获带有循环引用的东西(其中计数永远不会变为 0)。在您的示例中,当您这样做时,按钮的引用计数变为 0:removeChild(myButton); myButton = null; 该按钮符合垃圾回收条件,但无法保证何时会发生。
    • 只是为了澄清和回答您评论中的具体问题:当您在按钮中使用 addEventListener() 时,按钮基本上将该事件映射到一个函数(在这种情况下在您的主类中定义)。因此,当按钮获得 g/c'd 时,此映射随之而来,并且可以认为事件侦听器不再存在。添加侦听器和/或使用弱引用仍然是一个好习惯:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-13
    相关资源
    最近更新 更多