可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Is it possible to programmatically force a full garbage collection run in ActionScript 3.0?
Let's say I've created a bunch of Display objects with eventListeners and some of the DO's have been removed, some of the eventListeners have been triggered and removed etc... Is there a way to force garbage collection to run and collect everything that is available to be collected?
回答1:
Yes, it's possible, but it is generally a bad idea. The GC should have a better idea of when is a good time to run than you should, and except for a very specific case, like you just used 500MB of memory and you need to get it back ASAP, you shouldn't call the GC yourself.
In Flash 10, there is a System.gc()
method you can call (but please don't, see above) - keep in mind System.gc() only works in the debugging version of Flash player 10+.
In Flash 9, there is an unsupported way to force it via an odd LocalConnection command, but it may not work in all versions. See this post by Grant Skinner.
回答2:
There is a new API for telling the GC that it might be a "relatively good moment" to collect.
See the Adobe API docs for
System.pauseForGCIfCollectionImminent
And also this Adobe blog post from shortly after the method was introduced in Player version 11
The method takes an "imminence" argument; basically, you feed in a low number (near 0.0) if you really want the collector to run, even if there has not been much activity (currently measured by bytes-allocated) since the last collection, and you feed in a large number (near 1.0) if you only want the collection pause to happen if we were already near the point where a collection would happen anyway.
The motivation here is for situations in e.g. games where you want to shift the point where GC's happen by a small amount, e.g. do the GC during a change of level in the game, rather than two seconds after the player started exploring the level.
One very important detail: This new API is supported by both the Release and the Debugger Flash Runtimes. This makes it superior to calling System.gc().
回答3:
For all currently released versions, System.gc() only works in the debug version of the Flash player and ADL (the debug environment for AIR apps). Flash player 10 beta currently does work in all flavors.
I agree with Davr, it's a bad idea to do. The runtime will usually have a better idea than you do.
Plus, the specifics of how the garbage collector works is an implementation detail subject to change between flash player versions. So what works well today has no guarantee to work well in the future.
回答4:
As others said: do not try to GC manually, there are hacks but it's not safe.
You should try recycling objects when you can - you'll save a lot of memory.
This can be applied for instance to BitmapDatas (clear and reuse), particles (remove from display and reuse).
回答5:
I have a comment on those saying you should never do GC manually. I'm used to manual memory management in C++ and I prefer sharedptr a lot over GC, but anyway.
There is a specific case where I can't find another solution than do a GC. Please consider: I have a DataCache class, the way it work is it keeps result objects for certain method calls that send out updated events when refreshing/receiving data. The way the cache is refreshed is I just clean all results from it and send the event which causes any remaining listeners to re-request their data and listeners that went out of scope should not rerequest which cleans out not needed results. But apparently, if I can't force all listeners that still dangle waiting for GC to be cleaned up immediatly before sending out the "ask you data again" event, those dangling listeners will request data again unnecessarily. So since I can't removeEventListener because AS3 doesn't have destructors I can't see another easy solution than forcing a GC to make sure there's no dangling listeners anymore.
(Edit) On top of that I cannot use removeEventListener anyway for binding which were setup in mxml, for example (using my custom DataCacher class which handles remoteobj)
<mx:DataGrid id="mygrid" dataProvider="{DataCacher.instance().result('method').data}" ... />
When the popup window containing this datagrid is closed, you would expect the bindings to be destroyed. Apparently they live on and on. Hmm, shouldn't flex destroy all bindings (meaning eventlisteners) from an object when it's being marked for GC because the last reference is deleted. That would kinda solve the problem for me.
At least that's why I think, I'm still a beginner in Flex so any thoughts would be appreciated.
回答6:
try {
new LocalConnection().connect('foo');
new LocalConnection().connect('foo');
} catch (e:*){
trace("Forcing Garbage Collection :"+e.toString());
}
回答7:
If you have to, calling the gargabe collector could be useful... so, you have to be carefull how and when you do it, but there is no doubt that there are times when is neccesary.
for example, if you have an app that is modular, when you change from one view to the other, all the deleted objects could represent a large amount of memory that should be available as faster as possible, you just need to have control of the variables and references you are disposing.
回答8:
recycling doesn't really help. I used one loader that repeatedly loaded the same jpg every 500ms. task manager still reported a non stop increase in memory.
tried and proven solution here.
http://simplistika.com/as3-garbage-collection/