在 AS3 中强制垃圾收集?
Posted
技术标签:
【中文标题】在 AS3 中强制垃圾收集?【英文标题】:Force Garbage Collection in AS3? 【发布时间】:2010-09-16 13:58:30 【问题描述】:是否可以以编程方式强制在 ActionScript 3.0 中运行完整的垃圾回收?
假设我用 eventListeners 创建了一堆 Display 对象,其中一些 DO 已被删除,一些 eventListeners 已被触发和删除等等......有没有办法强制垃圾收集运行和收集所有可以收集的东西?
【问题讨论】:
【参考方案1】:是的,这是可能的,但这通常是个坏主意。 GC 应该比你应该更好地知道什么时候是运行的好时机,除了非常特殊的情况,比如你刚刚使用了 500MB 内存并且你需要尽快取回它,你不应该调用 GC自己。
在 Flash 10 中,您可以调用 System.gc()
方法(但请不要调用,见上文) - 请记住 System.gc() 仅适用于 Flash player 10+ 的调试版本。
在 Flash 9 中,有一种不支持的方式通过奇怪的 LocalConnection 命令强制它,但它可能不适用于所有版本。请参阅 Grant Skinner 的 this post。
【讨论】:
这是一个很好的答案 - 但错过了一个非常重要的点。无论如何,它只适用于调试播放器! System.gc() - 仅适用于 Flash Player 调试器版本和 AIR 应用程序。在 AIR 应用程序中,System.gc() 方法仅在 AIR 调试启动器 (ADL) 中运行的内容中启用,或者在已安装的应用程序中,在应用程序安全沙箱中的内容中启用。 [livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/system/… 在 Flash 11 中有一个可以调用的System.pauseForGCIfCollectionImminent()
方法。它需要一个参数,以便您可以让 GC 了解收集需要多近的时间才能发生暂停。有关更多详细信息/链接,请参阅下面的答案。【参考方案2】:
对于所有当前发布的版本,System.gc() 仅适用于 Flash 播放器和 ADL(AIR 应用程序的调试环境)的调试版本。 Flash player 10 beta 目前适用于所有版本。
我同意 Davr,这是个坏主意。运行时通常会比你有更好的主意。
另外,垃圾收集器如何工作的细节是一个实现细节,可能会在 Flash 播放器版本之间发生变化。所以今天行得通的东西并不能保证将来也行得通。
【讨论】:
有一个特定的案例,我有一个 DataCache 类,它的工作方式是在刷新/接收数据时保持结果对象发送更新的事件。清理缓存的方式是我只清理其中的所有结果并发送导致任何剩余侦听器重新请求其数据的事件。如果我不能强制所有仍然悬空等待 GC 在发送刷新事件之前立即清理的侦听器,那些悬空的侦听器将再次请求数据。【参考方案3】:正如其他人所说:不要尝试手动 GC,有 hack 但不安全。
你应该尽可能地尝试回收对象 - 你会节省很多内存。
这可以应用于例如 BitmapDatas(清除和重复使用)、粒子(从显示中删除和重复使用)。
【讨论】:
【参考方案4】:我对那些说你永远不应该手动进行 GC 的人发表评论。我习惯于在 C++ 中手动管理内存,我更喜欢 sharedptr 而不是 GC,但无论如何。
在特定情况下,我找不到除 GC 之外的其他解决方案。请考虑:我有一个 DataCache 类,它的工作方式是为某些在刷新/接收数据时发送更新事件的方法调用保留结果对象。刷新缓存的方式是我只是清除其中的所有结果并发送导致任何剩余侦听器重新请求其数据的事件,超出范围的侦听器不应该重新请求清除不需要的结果。但显然,如果我不能强制所有仍然悬空等待 GC 在发送“再次询问数据”事件之前立即清理的侦听器,那些悬空的侦听器将不必要地再次请求数据。因此,由于 AS3 没有析构函数,因此我无法删除EventListener,因此除了强制 GC 确保不再有悬空的侦听器之外,我找不到其他简单的解决方案。
(编辑)除此之外,我无论如何都不能使用 removeEventListener 来绑定在 mxml 中设置的绑定,例如(使用处理 remoteobj 的自定义 DataCacher 类)
<mx:DataGrid id="mygrid" dataProvider="DataCacher.instance().result('method').data" ... />
当包含此数据网格的弹出窗口关闭时,您会期望绑定被破坏。显然,他们一直生活下去。嗯,当对象被 标记 进行 GC 时,不应该 flex 销毁对象的所有绑定(即事件侦听器),因为最后一个引用已被删除。这对我来说有点解决问题。
至少这就是我认为的原因,我仍然是 Flex 的初学者,所以任何想法都将不胜感激。
【讨论】:
【参考方案5】:如果必须,调用 gargabe 收集器可能会很有用......所以,你必须小心如何以及何时这样做,但毫无疑问,有时是必要的。
例如,如果您有一个模块化的应用程序,当您从一个视图切换到另一个视图时,所有已删除的对象可能代表大量内存,应该尽可能快地可用,您只需要拥有控制您正在处理的变量和引用。
【讨论】:
【参考方案6】:回收并没有真正的帮助。我使用了一个加载器,它每 500 毫秒重复加载相同的 jpg。任务管理器仍然报告内存不断增加。
这里经过验证的解决方案。
http://simplistika.com/as3-garbage-collection/
【讨论】:
【参考方案7】:try
new LocalConnection().connect('foo');
new LocalConnection().connect('foo');
catch (e:*)
trace("Forcing Garbage Collection :"+e.toString());
【讨论】:
你能解释一下与 GC 的链接是什么以及为什么这会强制它吗?【参考方案8】:有一个新的 API 可以告诉 GC 这可能是一个“相对好的时机”来收集。
请参阅 Adobe API 文档了解 System.pauseForGCIfCollectionImminent
还有这个 Adobe blog post 在播放器版本 11 中引入该方法后不久
该方法采用“紧迫性”参数;基本上,如果您真的希望收集器运行,您可以输入一个较低的数字(接近 0.0),即使自上次收集以来没有太多活动(当前以分配的字节数衡量),并且您输入的数字很大( 1.0 附近),如果您只希望在我们已经接近无论如何都会发生收集的点时发生收集暂停。
这里的动机是针对例如您想要将 GC 发生点稍微移动的游戏,例如在游戏中的关卡变化期间进行 GC,而不是在玩家开始探索关卡后两秒。
一个非常重要的细节:Release 和 Debugger Flash Runtimes 都支持这个新 API。这使它优于调用 System.gc()。
【讨论】:
以上是关于在 AS3 中强制垃圾收集?的主要内容,如果未能解决你的问题,请参考以下文章