JavaやC#にポインタが存在しないのは,その存在を不要にする仕組みがあるからだ。JavaもC#も,基本的にC/C++と同じデータ領域の確保の仕方を採っている。つまり,スタックとヒープに相当するものを持っている。Java/C#のいずれもこういった呼び方はしていないが,考え方は同じだと思ってよい。

 JavaおよびC#では,データ型が大きく分かれて2種類ある。Javaではプリミティブと参照型と呼ぶ。C#では値型と参照型と呼ぶ。参照型がオブジェクトを表現するデータで,プリミティブは単純なデータ型である。C#にはJavaにはない構造体などの複合データ型も定義できる。これはオブジェクトとは異なり,値型として扱われる。

 JavaやC#がこのように二つのデータ型の体系を備えているのは,性能とプログラミングするうえでのわかりやすさのバランスを取った結果である。オブジェクトに関しては,参照と実体が両方存在するC++の方式はとてもわかりにくい。メモリ・リークのことも含め,誤りの元である。例えばC++では,参照型(ポインタ)の場合と,実体型の場合でメンバ変数やメソッド呼び出しの演算子が異なる。前者は「->」,後者は「.(ピリオド)」になる。こういった違いは,誤りを生みやすい。C#やJavaでは,すべて参照型なので「.」で統一できる。

性能のために2種の変数がある

リスト4●JavaのVectorクラスに数値のデータを格納するプログラム。
Integerクラスを生成して数値をラップしている

 しかし参照型のデータだけにしてしまうと,性能が落ちてしまう。Smalltalkに代表される純オブジェクト指向プログラミング環境では,数値などの単純な型であってもオブジェクトとして実装される。しかし例えば,「1+2」を実行するのにこのような手順になる。(1)整数オブジェクトの実体を作り,初期値に1を与える,(2)それを参照する仮の入れ物を作る,(3)同様に2の整数オブジェクトを生成する,(4)オブジェクト1のメソッド「+」を,(3)で作ったオブジェクトの参照値を引数として呼び出す。これを「値」として処理するなら,いちいちオブジェクトを生成する必要がない。

 言語体系としての統一性には欠けるため,問題がゼロというわけではない。例えばプリミティブや値型のデータを,オブジェクトを格納するコレクション型のデータで管理できないという問題がある(リスト4[拡大表示])。いちいちプリミティブ型のデータを,相当するオブジェクト型のデータに変更してから,該当するコレクションに入れてやる必要がある。また,コレクションから取り出すときには,適切な型に変換してやる必要もある。手間もかかるし,トラブルの原因となりかねない。C#にはBoxingという機能があるので,Javaより多少見栄えはよいが,本質的には同じ問題を抱えている。

図5●メモリ管理とガベージ・コレクション。
JavaやC#では,オブジェクトを生成するとポインタとその実体のペアが作られる。両者の関連を維持しているのがメモリ管理機構である。メモリ管理機構はオブジェクトの消去も担当する。ポインタだけでなく,実体の領域も解放する。そして必要に応じて,オブジェクトの領域を整理するガベージ・コレクションを実行する

メモリ管理するのでメモリ・リークはない

 JavaやC#において,メモリ・リークが発生しない最大の理由は,メモリ管理機構を実行環境が備えていることにある。メモリ管理機構の役割は大きく二つ。スコープからはずれたオブジェクトを正しくメモリ空間から解放することと,虫食い状態になったメモリを適切に再配置することである(図5[拡大表示])。よく「ガベージ・コレクションがあるからJavaにはメモリ・リークがない」という表現を見かけるが,半分正しく,半分間違っているというところだろう。メモリ・リークがないことは,ガベージ・コレクションと直接つながっていない。ガベージ・コレクション自体はあくまでも「ゴミ集め」なのである。ヒープの状態は,解放された部分と生きているオブジェクトが混在している。こうなっているとメモリを効率よく使えないので,一度整理して集めてやらなければならない。この作業がガベージ・コレクションなのである。ただし,ガベージ・コレクションを実行すると,当然オブジェクトの位置が変わることになる。これを正しく参照している変数の方にも反映させなければならない。こういったことを実現するには,適切なメモリ管理の機構が必要となる。だからガベージ・コレクションを実装した処理系は,メモリ管理もしている。つまり,メモリ・リークも存在しない,ということになる。

「よくメモリはハコだとか言うんですけど,最初納得いかなかったんですよね」
「うーん。アセンブラをやってれば,わかりやすいイメージなんだけどな」
「だってハコはハコじゃないですか。メモリにマッピングされる,ということだって,最初はわかんないんですよ。アドレスは住所だとか言われるし」
「メタファって,理解してから聞くととてもよくわかるけど,理解せずに聞くとかえってわからなくなるのかもしれないね。またそれが,今自分の目の前にあるコンピュータとどう結びつくのか,イメージしにくいよね」

(北郷 達郎、八木 玲子)