18

是否可以以编程方式强制在 ActionScript 3.0 中运行完整的垃圾回收?

假设我创建了一堆带有 eventListeners 的 Display 对象,并且一些 DO 已被删除,一些 eventListeners 已被触发和删除等等......有没有办法强制垃圾收集运行并收集所有内容可以收集吗?

4

8 回答 8

25

是的,这是可能的,但这通常是一个坏主意。GC 应该比你应该更好地知道什么时候是运行的好时机,除了非常特殊的情况,比如你刚刚使用了 500MB 内存并且你需要尽快取回它,你不应该调用 GC你自己。

在 Flash 10 中,有一个System.gc()方法可以调用(但请不要调用,见上文) - 请记住 System.gc() 仅适用于 Flash player 10+ 的调试版本。

在 Flash 9 中,有一种不受支持的方法可以通过奇怪的 LocalConnection 命令强制它,但它可能不适用于所有版本。请参阅格兰特斯金纳的这篇文章

于 2008-10-10T17:45:09.223 回答
15

有一个新的 API 可以告诉 GC 这可能是一个“相对好的时刻”来收集。

有关System.pauseForGCIfCollectionImminent的信息,请参阅 Adob​​e API 文档

以及在 Player 版本 11 中引入该方法后不久的这篇Adob​​e 博客文章

该方法采用“迫在眉睫”的论点;基本上,如果您真的希望收集器运行,您可以输入一个较小的数字(接近 0.0),即使自上次收集以来没有太多活动(当前以分配的字节数衡量),并且您输入的数字很大( 1.0 附近)如果您只希望在我们已经接近无论如何都会发生收集的点时发生收集暂停。

这里的动机是针对例如游戏中的情况,您希望将 GC 发生的点移动少量,例如在游戏中的关卡更改期间进行 GC,而不是在玩家开始探索关卡后两秒。

一个非常重要的细节:Release 和 Debugger Flash Runtimes 都支持这一新 API。这使它优于调用 System.gc()。

于 2012-07-12T10:45:25.273 回答
8

对于所有当前发布的版本,System.gc() 仅适用于 Flash 播放器和 ADL(AIR 应用程序的调试环境)的调试版本。Flash 播放器 10 测试版目前适用于所有版本。

我同意 Davr,这是一个坏主意。运行时通常会比你有更好的主意。

另外,垃圾收集器如何工作的细节是一个实现细节,可能会在 Flash 播放器版本之间发生变化。所以今天行得通的东西并不能保证将来也行得通。

于 2008-10-10T19:58:36.223 回答
3

正如其他人所说:不要尝试手动 GC,有黑客攻击但不安全。

您应该尽可能地尝试回收对象 - 您将节省大量内存。

例如,这可以应用于 BitmapDatas(清除和重用)、粒子(从显示中删除和重用)。

于 2008-10-12T15:33:28.613 回答
3

我对那些说你永远不应该手动进行 GC 的人发表评论。我习惯于在 C++ 中手动管理内存,并且我更喜欢 sharedptr 而不是 GC,但无论如何。

在特定情况下,我找不到除 GC 之外的其他解决方案。请考虑:我有一个 DataCache 类,它的工作方式是为某些在刷新/接收数据时发送更新事件的方法调用保留结果对象。刷新缓存的方式是我只是清除其中的所有结果并发送导致任何剩余侦听器重新请求其数据的事件,并且超出范围的侦听器不应该重新请求清除不需要的结果。但显然,如果我不能强制所有仍然悬空等待 GC 在发送“再次询问数据”事件之前立即清理的侦听器,那些悬空的侦听器将不必要地再次请求数据。所以因为我不能 removeEventListener 因为 AS3 没有析构函数,所以我不能

(编辑)除此之外,我无论如何都不能使用 removeEventListener 进行绑定,这些绑定是在 mxml 中设置的,例如(使用我的自定义 DataCacher 类来处理 remoteobj)

<mx:DataGrid id="mygrid" dataProvider="{DataCacher.instance().result('method').data}" ... />

当包含此数据网格的弹出窗口关闭时,您会期望绑定被破坏。显然,他们一直生活下去。嗯,当对象被标记为 GC时,不应该从对象中销毁所有绑定(即事件侦听器),因为最后一个引用已被删除。这对我来说有点解决问题。

至少这就是我认为的原因,我仍然是 Flex 的初学者,所以任何想法都会受到赞赏。

于 2010-02-19T10:10:50.430 回答
3
try {
    new LocalConnection().connect('foo');
    new LocalConnection().connect('foo');
} catch (e:*){
    trace("Forcing Garbage Collection :"+e.toString());
}
于 2011-04-19T16:05:16.867 回答
0

如果必须,调用 gargabe 收集器可能会很有用......所以,你必须小心如何以及何时这样做,但毫无疑问,有时是必要的。

例如,如果您有一个模块化的应用程序,当您从一个视图更改为另一个视图时,所有已删除的对象可能代表大量内存,应该尽可能快地可用,您只需要控制您正在处理的变量和引用。

于 2010-09-17T20:14:32.673 回答
0

回收并没有真正的帮助。我使用了一个加载器,它每 500 毫秒重复加载相同的 jpg。任务管理器仍然报告内存不断增加。

在这里尝试和证明的解决方案。

http://simplistika.com/as3-garbage-collection/

于 2010-11-10T00:53:00.117 回答