Memory/reference leakage in flash player
下面的例子示範了在 AS3 編程時,一不小心就會造成 memory leak。
-
private var p:Person;
-
private var arr:Array = [];
-
-
private function init():void{
-
p = new Person();
-
p.theName = "fooooooooooooooobarrrrrrrrrrr";
-
this.theText.text = p.theName;
-
//
-
arr.push( p );
-
//
-
this.theList.dataProvider = arr;
-
}
-
-
private function doClear():void{
-
p = null;
-
arr = null;
-
//this.theList.dataProvider = null;
-
trace("p: ", p);
-
}
主要的原因是:
1、FP9 的 Grabage Collection 是採用 reference counting,當一個物件生成後只要有被其它物件 reference 一次,它的 reference count 就會 +1,也就是說在下次 gc 發生時它不會被 mark and sweep。
2、以上面的例子,當一個 person instance 建立後,它被放進 arr,然後 arr 被指派為 List 的 dataProvider,這樣它就有兩個 reference counts了。
3、當執行 doClear()時,雖然將 p 設為 null,同時也清空了 arr的內容,但很不幸的,person instance 仍然存在。
4、原因是當 arr 被設為 List.dataProvider 時,在 List 內部就產生了一個 reference,這個可以從 debugging > variable 看出來,實際上在 List 裏面是產生了兩個 reference了,分別放在 source 與 list 這兩個變數裏。

這件事情的嚴重性在於,當程式執行階段要處理的 value object 非常多時,時間一久,memory leakage 就會無限擴大,而且最糟糕的是 gc 也幫不上任何忙,因此它會認為 person 還有被用到本來就不可以被清掉。
所以該怎麼辦呢?
很簡單,從現在開始起,AS3 developer 也要像 c/c++/java developer 一樣,個已負起記憶體管理的責任,心裏要清楚知道每個物件目前身處何方?它的 reference 數量?以及那些操作可能會造成reference leak?接者就是在物件不需被用到時勤快的將它們清掉。
在未來,Adobe 會推出 profiler 等工具讓 developer 可以比較輕鬆的觀察物件的生命狀態與記憶體配置,就會比較容易找出 leakage,但在那之前(預估還要半年),大家就靠自已吧...


7 Comments Add your own
1. iiley&hellip | November 29th, 2006 at 1:21 pm
我觉得这是再正常不过的事情了,在AS2中,也肯定是这样的。Person还存在引用,还在被List使用中,当然不会被回收。这种情况我想任何正确的垃圾回收机制都不会回收它,因为本来就不应该回收它,除非你消除所有的引用。(当然Java里面有弱引用WeeknessReference,弱引用好像是不会被count的,不知道AS3里面有没有,还不熟悉AS3)
2. jeremy&hellip | November 29th, 2006 at 1:32 pm
AS3 裏的 Dictionary 與 addEventListener() 有支援 weak reference, 但 AS3 language level weak reference support 據說要下一版才會放進去。
上面這篇文章主要強調的就是:消除所有的 reference 從此變成是developer 要時時關心的事,不能以為看不見就當沒這回事
3. Dreamer&hellip | December 1st, 2006 at 9:55 am
这些事情对于developer出身的应该是家常便饭了,不过研究Flash很多都是designer
4. jeremy&hellip | December 1st, 2006 at 10:27 am
呵,我問了幾位寫java的朋友,包括[大長輩]在內,都說平常不會去特別注意這種事...
後來進一步討論,很驚訝的發現要造成reference leakage是多麼容易的事,就算再小心,也還是有可能無意間讓它發生。
5. Hiso&hellip | December 3rd, 2006 at 3:36 am
我寫了一個簡單的記憶體監視器,可以試試看.
http://www.iamhiso.com/nfblog/?p=44
6. jeremy&hellip | December 3rd, 2006 at 10:39 am
hiso, 那個圖表跑了一段時間後,我猜一定會出現經典的 tooth saw (鋸齒狀)圖案,因為 gc 每隔一段時會發動一次,這時 memory usage 就會 drop 下來,然後再緩慢攀伸。
7. Hiso&hellip | December 3rd, 2006 at 3:07 pm
啊,我那不是燒機程式,只是記憶體監看器,
是用來看自己開發flex app,對記憶體狀況的異常控制,
主要用來看行為操作後圖形的高低變化,
例如對某元件重復add,remove時,是否記憶體還是直線增加,或是看使用panel或titlewindow時,那一個記憶體增加的比較多.
可能demo的環境太單純,才沒什麼變化性.
因為目前我只寫一種簡單監看方式,
且為了避免記錄用的ArrayCollection變的太龐大,
所以每到20筆資料時,就會把ArrayCollection內的資料筆數減半,檢查記憶體的時間間距加倍,轉而變長時間記憶體變化之呈現.
至於自動gc動作,一般小程式的資料結構本來就不大,應該在圖形上的變化有限,所以我是沒特別用這程式來表現那一塊.
Trackback this post | Subscribe to the comments via RSS Feed