2008年最初の、ダイナミックObjective-Cの更新だ。今年もよろしくお願いします。

振り返ってみると、2007年はLeopardとObjective-C 2.0が登場した、動きの多い年だった。今年は、それらの新技術を取り込み、消化して、実践の場に移す年になるだろう。また、iPhone SDKの登場も予告されている。新たなObjective-Cプラットフォームの誕生だ。パソコンだけでなく、モバイル機器にもObjective-Cの活躍の場は広がっていくことになるだろう。

では、ガベージコレクションの話を続けよう。今回は、Objective-C 2.0に実装されているガベージコレクションが、どのような性質のものに分類されるのか調べてみる。

Objective-Cガベージコレクションの性質

Objective-Cという言語にガベージコレクションを導入する場合、考慮するポイントは、2つ挙げることができるだろう。

1つは「ポインタを使っている」ということだ。C言語の文法をそのまま内包し、コンパイルしてネイティブコードを作成するタイプの言語なので、ポインタが利用可能になっている。だが、ガベージコレクションを適用することを考えると、これは大きな制約になる。

もう1つは、オブジェクトが存在することだ。つまり、id型が指し示すオブジェクトとして取り扱われるメモリの領域があるということだ。これは、ガベージコレクションの導入に有利に働くだろう。

つまり、Objective-Cのガベージコレクションの性質をざっくりと言ってみれば、C言語のみによるものよりは賢く、ポインタを許さないスクリプティング言語などと比べれば制約を受ける、となるだろう。

もう少し詳しく見てみよう。次のように分類することができる。

Objective-Cのガベージコレクションは、保守的であり、コピーは行わず(ゆえにコンパクションも行わない)、マーク・アンド・スイープでコレクションを行い、世代別コレクションをサポートする

これらの用語について、説明していこう。

保守的なガベージコレクション

まず、「保守的」という語を説明しよう。

ガベージコレクションの設計をする上で、最も大切なことは何であろう? それは、まだ必要なメモリ領域を誤って解放することは絶対にあってはならない、ということだ。それに対して、この逆、必要とされていない領域の解法忘れは、メモリリークにつながるが、クリティカルさの度合いでは低くなるだろう。

では、必要とされるメモリ領域はどうやって判定すればいいだろうか。C言語やObjective-Cのようなポインタを許すプログラミング言語では、有効なポインタによって指し示されている領域が必要なもの、となるだろう。

だが、ここで1つ問題が起こる。ポインタとは、プログラム上では、ただの整数値である。従って、ある整数値があったとき、それがポインタなのか単なる整数値なのかを見分けることは、厳密には不可能になる。

ただ実際のところは、ポインタはmallocなどによって確保されたメモリ領域の先頭を指し示すことになるので、ある程度は見分けることは出来る。だが100%確実ではない。ガベージコレクションにおいて、メモリ領域を見誤って必要領域を解放をすることは決してあってはならないので、怪しい領域は解放しないようにするのだ。これが「保守的」と呼ばれる所以である。

これに対して、ポインタを許さない環境では、このような問題は起こらないはずだ。保守的ではない、厳密なガベージコレクションが可能だろう。

クローズドシステム対オープンシステム

さて、ここでObjective-Cのランタイムを考えてみよう。Objective-Cでは、ポインタの使用を許している。従って、保守的なガベージコレクションでなくてはならない。だが同時に、オブジェクトも規定している。ならばそれを利用したコレクションもできるだろう。

Appleのドキュメントでは、この2つのシステムを指して、「クローズド」なシステムと「オープン」なシステムと呼んでいる。クローズドなシステムとは、言語、コンパイラ、ランタイムが囲い込まれており、すべてのメモリ領域がガベージコレクションの対象にできるようなシステムのこと、と定義されている。つまり、スクリプティング言語環境のようなものだ。C言語のような、ポインタを使ってメモリのどこでも指すことができるシステムは、オープンなシステムということになる。

単にガベージコレクションを実現するだけならば、クローズドシステムのほうが都合がいい。だが、C言語ライブラリの可搬性や、単純な実行速度を考えると、ポインタを使った方が効率がいいだろう。

そこで、Objective-Cのガベージコレクションは、このクローズドシステムとオープンシステムの間で、バランスを取ったものになる。具体的には、ガベージコレクションの探索度合いを、いくつかに分けているようだ。浅い探索では、id型のオブジェクトのみになる。このときはクローズドシステムと似たような性質を持ち、世代別ガベージコクレションなども可能になる。もっと深く、すべてのメモリ領域を探索するようなときは、保守的ガベージコレクションを行うわけだ。

これが、Objective-Cガベージコレクションの基本方針となる。ポインタが使用可能であるという、ガベージコレクションにとって最大の泣き所を、いかにうまく立ち回って回避するかという工夫が見られるところだ。