Luar's Flash Playground:神秘的Garbage Collection
神秘的Garbage Collection (29-10-2004)

當一個Variable/Object不再需要時,就應該刪除/釋放,以讓出Memory,這種Memory資源管理,稱為Garbage Collection(垃圾回收),簡稱gc。在Flash裡面,熟悉的所謂gc做法有兩種,針對Variable/Object,可以用delete,針對Movie Clip,可以用removeMovieClip()。現實上,delete真的可以刪除垃圾,釋放Memory?當然不是,因為ActionScript裡,凡Array、Object和Function(下面統稱為OBJECTS)的創建,等於建立一個Reference指向Memory某個被佔用位置;因此,當delete OBJECTS時,只不過是刪除這個Reference,斬斷連繫,被佔用Memory仍然存在,根本沒有做到gc。以下是兩個例子:

var ref1:Object = new Object();
ref1.name = "Luar";
ref2 = ref1;            // 複製新Reference到另一個Variable
delete ref1;            // 然後刪除ref1
trace(ref1.name);    //output: undefined
trace(ref2.name);    //output: Luar
myfunction = function () {
    trace('Still Here');
};
myOtherfunction = myfunction;
delete myfunction;
myOtherfunction();    //output: Still Here
因此,第一次建立OBJECTS,例如ref1、myfunction,是同時做了malloc和建立Reference兩件事,但delete OBJECTS時,只做了刪除Reference,沒有做unmalloc。(註:malloc/unmalloc是C指令,用來分配(佔用)/釋放Memory空間)

根據Flash Help,當一個Memory位置再沒有任何Variable指向Reference它(例如ref1和ref2都delete了),就會自動釋放,換句話說,Flash Player自動替開發者做gc,實在是太好了。原文:You can use the delete operator to remove references to objects. After all references to an object are removed, Flash Player takes care of removing the object and freeing the memory used by that object.

不過,別太早高興,究竟這個自動gc是何時會發生?即時?下一個Frame?沒有人知道。

Movie Clip是Flash獨有的東西,其他編程語言所沒有,由於歷史因素,Movie Clip仍然是用它獨有的建立Object做法:attachMovie()、duplicateMovieClip()和createEmptyMovieClip(),與及獨有的刪除Object做法:removeMovieClip()。(註:unloadMovie()只是將Movie Clip裡東西弄走,沒有刪除Movie Clip)

創建Movie Clip時,可以用一個Variable代表,例如:

var myMC = _root.attachMovie("circle", "circle_"+i, i);
避免那用Array Operator("[]")砌出來長長的的Movie Clip名稱,例如:
_root["circle_"+i].gotoAndPlay(2);
先用這情況對剛才所講解gc作比喻,Movie Clip好像Memory,myMC好像OBJECTS,刪除了myMC,Movie Clip仍然存在。

提及Movie Clip創建,當然不是只用來作比喻,這裡要提出一個問題,現在用myMC代表了Movie Clip,換句話說,用

myMC.removeMovieClip();
_root["circle_"+i].removeMovieClip();
都可以刪除這個Movie Clip,當直接用Movie Clip名刪除後,myMC是不知道的!它仍然繼續指向undefined,它其實已經沒有用,應該都要刪除。

當然,只要刪除Movie Clip時,同時刪除myMC就可以:

_root["circle_"+i].removeMovieClip();
delete myMC;
但這不是好辦法。

當Movie Clip被刪除時,會發生onUnload事件,利用它,臨死前將myMC一併刪除,但Movie Clip怎知道代表它的Variable是什麼呢?只好在Movie Clip創建時,利用initObject同時告訴Movie Clip,例如:

var myMC = _root.attachMovie("circle", "circle", 0, {objName:"myMC"});
這樣再擴建MovieClip的方法:
MovieClip.prototype.onUnload = function() {
    delete this._parent[this.objName];
};
[下載範例]

好了,以上的講解,究竟和Design Patterns有什麼關係?因為Movie Clip經常被Composite到其他Object裡,下次繼續。

本文章由發表。
意見
"; print "沒有意見。
 "; } ?>
  • good ,期待下文........

    jackyshe於29-10-2004發表

  • 謝謝捧場 :)

    luar於29-10-2004發表

  • Garbage Collection 通常是系統資源不足先會運作,因為如果時常刪除 memory ,會容易做成 memory hole,那麼 OS 便要搬移 memory 去消去這些 memory hole ,間接影響了程式效能!
    (搬移 memory 和硬碟重組差不多)

    Solomon@SW2於29-10-2004發表

  • 不知道Flash Player有沒有這能力知道自己拖累了系統? ;)
    不過依我經驗所見,當Flash越來越慢時,只會一直越來越慢,不見得會有gc出現。

    luar於29-10-2004發表

  • Talking about gc, director got an undocumented thing gc()

    http://nuttybar.drama.uga.edu/pipermail/dir3d-l/2004-May/ 006278.html

    maybe Flash has something like this too.

    由sim_irv於29-10-2004發表

  • 學到不少,感謝分享~

    由maso於29-10-2004發表

  • 以前做flashcom聊天室,就是因為沒刪除舊留言弄掛掉...真的很棒的文章

    由kyle於29-10-2004發表

  • 有些意思。

    由幻鲨於30-10-2004發表

  • myMC是一個reference,佔的記憶體必定非常小,會對系統產生多大的影響令人質疑.若不刪除它也另有用途,可以做為其他物件的reference.

    ejann於01-11-2004發表

  • Java gets garbage collector too. Perhaps java also face the same situation, but is it?

    由Warenix於04-11-2004發表

  • var obj = new Object();
    obj.myMC = _root.attachMovie("circle", "circle", 0, {objName:"myMC"});
    这种情况不行,路径问题...

    magicwind於10-11-2004發表

  • 怎麽我上午發的comment不見了?

    我覺得第一個例子沒有錯的:
    http://blog.csdn.net/qhwa/archive/2004/11/23/191863.aspx

    由qhwa於23-11-2004發表

同組文章