AS3メモ ガベッジコレクションについて
どうやら、色々な偉い人の話をまとめると、ガベージコレクションの仕組みを知らずにAS3でコードを組むと、ハングアップの危険がいっぱいということみたい。
とりあえず理解しなければならないのは delete の新しい挙動と、リファレンス・カウント、マーク&スイープという概念らしい。
ガベージコレクターとは何か?
ガベージコレクターとは、Flashプレイヤー上でいらなくなったオブジェクトやローカル変数を管理して、メモリー上から自動で削除する仕組みのこと。 こいつのおかげで、ASのプログラマーはポインターとかメモリーの解放とかを意識しないですんでいるわけです。で、AS3使いは、どのような条件化でガベージコレクターがゴミ変数を削除してくれるか、という条件を理解しないといけないのだそうです。
リファレンス・カウント
AS3では、オブジェクトの参照を作るたびに、そのオブジェクトへの参照数を表すリファレンスカウントというカウントがバックグラウンドで行われています。
var a:Object = new Object() //これでリファレンスカウント1
var b:Object = a //これでリファレンスカウント2
で、逆にdeleteによってオブジェクトの参照を削除すると、このカウントは減っていきます。
var a:Object = new Object() //これでリファレンスカウント1
var b:Object = a //これでリファレンスカウント2
delete b //カウントが1に戻る
ちなみに、注意しなければいけないのは「deleteはオブジェクトそのものは削除せず、単に変数のオブジェクトへの参照を取り消すだけ」だということです。delete を呼んだだけでは、オブジェクトは削除されません。単にそのプロパティからの参照がなくなり、オブジェクトへのリファレンスカウントは1つ減少するだけです。
では、実際の削除はいつ行われるのか?というと、デリートやローカル変数の削除によって、オブジェクトのリファレンスカウントが0になったときに初めてガベージコレクターによって回収されます。
ちなみに、AS3では変数のプロパティに対しては delete が使えないので、プロパティ変数内の参照を殺す場合には、変数にnullを突っ込みます。
リファレンスカウントの問題点
さて、このリファレンスカウントですが1つ大きな問題点があります。例えば、下のようなコードを書いた場合。
var a:Object = new Object(); //オブジェクト甲
var b:Object = new Object(); //オブジェクト乙
a.b = b
b.a = a
delete a
delete b
このコードでは、オブジェクト甲と乙をそれぞれ変数a,bに代入し、オブジェクト甲のプロパティbにオブジェクト乙を、オブジェクト乙のプロパティaにオブジェクト甲を代入してから、変数a, bの参照を削除しました。
この場合、変数a, bを削除しても、作成された2つのオブジェクト甲、乙のリファレンスカウントは0になりません。なぜならば、オブジェクト甲の参照はオブジェクト乙のプロパティbによって、オブジェクト乙の参照はオブジェクトプロパティ甲のプロパティaによって保持されている為です。 ただし、変数a,bは既に削除されていますので、この2つのオブジェクトは存在するものの、アクセスする手段はいっさいありません。