没有System.gc()调用就没有删除对象

时间:2012-01-23 23:50:33

标签: flash actionscript-3 garbage-collection

在删除对象时出现问题,我进行了一个简单的测试:

  1. 为Event.ENTER_FRAME创建了一个带有弱引用侦听器的简单类。
  2. 为已侦听的功能添加了trace("I Exist!")次调用。
  3. 在文档类中实例化一个带有一个引用的实例。
  4. 这按预期工作 - SWF文件除了打印“I Exist!”之外什么也没做。每一帧到控制台。 (当然,在调试模式下。)

    我接下来做的事情并没有像我预期的那样奏效:
    我在鼠标事件上设置了要设置为null的对象的唯一引用,但是在触发鼠标事件并且引用设置为{后,来自所述对象的事件侦听器的消息仍然出现在控制台中{1}} - 意味着对象仍然存在!

    在文档类中调用 null IMMEDIATELY会阻止事件侦听器打印更多邮件,并且似乎已删除该项目。

    根据我的理解,不鼓励调用System.gc(),但从这个简单的测试来看,垃圾收集器是一个很大的失败。
    我在尝试处理对象时做错了什么,或者我每次想要摆脱一个对象时都应该简单地调用System.gc()。?

    编辑:使用非弱侦听器调用System.gc()也会导致对象似乎从内存中移除(?)

4 个答案:

答案 0 :(得分:3)

垃圾收集几乎总是在现代VM(Java,Flash Player,.NET等)中推迟。您可以阅读http://www.adobe.com/devnet/flashplayer/articles/garbage_collection.html了解更多信息。

特别是:

  

在Flash Player 9中,垃圾收集器的操作被延迟。这是一个非常重要的事情要理解。删除所有活动引用后,不会立即删除对象。相反,它们将在未来某个不确定的时间被删除(从开发人员的角度来看)。垃圾收集器使用一组启发式方法来查看RAM分配和内存堆栈的大小,以确定何时运行。作为开发人员,您必须接受以下事实:您将无法知道何时,甚至是否将释放您的非活动对象。您还必须意识到非活动对象将继续无限期地执行,直到垃圾回收器解除分配,因此您的代码将继续运行(enterFrame事件将继续),声音将继续播放,加载将继续发生,其他事件将继续发射,等等。

答案 1 :(得分:1)

实际上这是Flash垃圾收集系统的预期行为。每次调用System.gc()或创建新对象(new关键字)时,垃圾收集例程都会运行。您应该允许GC自然地清理对象,并且无论如何System.gc()仅适用于调试播放器,并且对发布版本没有任何作用。

如果您希望侦听器触发,则最好使用removeEventListener自行手动删除侦听器。但是,如果您不关心下一个收集阶段之前存在的功能,您可以依靠弱监听器。希望这会有所帮助。

答案 2 :(得分:0)

Garbage collection is only triggered by allocation in Flash Player意味着将对象设置为null不会导致调用垃圾收集器。

将对象设置为null只会删除对该对象的特定引用。事实上,你的监听器仍然有一个对象的引用,在你的情况下它是一个弱引用,所以当GC运行时,对象被收集,但在此之前它仍然在内存中挂起 - 调度并接收你设置它的任何事件处理

处理此问题的正确方法是显式删除您不再需要的任何事件侦听器,然后让GC在其良好且准备就绪时执行其操作。通常我会通过在我的类中添加destroy()方法来处理这个问题,这样我们就可以在我离开之前清理它们自己的混乱。

答案 3 :(得分:-1)

您确定删除了对象的所有引用吗?即你是否删除了鼠标事件监听器,如果你将对象添加到舞台上,你是否删除了儿童?

一旦确定所有引用都已删除,请将对象置零

object = null;

然后重要的是调用System.gc()TWICE

垃圾收集卡有两个阶段,Mark和Sweep。每次调用System.gc()只执行一个阶段。

这是一篇很棒的文章和工具,可让您跟踪应用中的对象,以便在任何时间点查看哪些对象仍然可以引用它们。

http://divillysausages.com/blog/tracking_memory_leaks_in_as3