13章 ガーベージコレクター |
1.ガーベージコレクターとは |
ガーベージ(garbage)とは、不要なデータのことである。不要になったデータを集めて処理する機能のことをいう。例えば、C++言語ではあるクラスのインスタンスを作成したら、プログラムでdeleteしないと不要データがいつまでもメモリー上に残ることになる。このことをメモリリークという。 また、削除してしまったインスタンスを参照したりするとエラーになりOSなどによってはそのまま暴走してしまうといったバグも発生する可能性がある。 しかし、javaではインスタンスを作成しても削除する必要がない。不必要になったインスタンスはこのガーベージコレクターがすべて処理してくれるからである。 |
class GarbageTest{ public static void main (String args[ ]){ String str1 = new String("abc); String str2 = new String("ABC); str2 = str1; // "ABC"という文字列はどこからも参照されなくなり、ガーベージコレクトの対象となる |
C:\java>javac *.java
C:\java>java GarbageTest C:\Mjava> |
2.ガーベージコレクターの実行 |
Java Virtual Machine(JVM)は、インスタンスの生成が行われた時など、メモリーを厳守監視している。これにより後でどのメモリー(インスタンス)が参照されていて必要なのか、あるいはもう参照されなくなって不必要になったのかを調べることができるようにしている。 しかし、不必要になったデータを探すのは、アプリケーションが大きくなればなるほど、時間がかかる処理になる。したがってJVMはデータが不必要になったらすぐにガーベージコレクトを行うのではなく、何もしていないときにガーベージコレクトを行うようにしている。 実際にガーベージコレクトが行われるタイミングはJVMの実装に任されており、プログラマやユーザがそのタイミングを関知しなくても良いことになっている。 |
Javaのメリットはプラットフォームを(OS)を選ばないことである。パソコンのようなメモリーの比較的豊富なプラットフォームで実行している分にはメモリーのことをそれほど意識しなくても良いのだが、携帯電話など比較的リソースの乏しいプラットフォームでJavaを実行する場合は、メモリーをできるだけ少なくして使用したい場合がある。このような場合、ガーベージコレクトをJVMに任せていてはメモリーが足りなくなってしまう。 もちろんメモリーを使用したい時に残りのメモリーが足りなくなればJVMはガーベージコレクターを起動させるが、もし時間的に余裕がない場合、実行されてしまっては困る。そこで、プログラマがガーベージコレクタを起動させるタイミングを指定することができる。それには、Systemクラスのgc( )メソッドを使用する。 それには、Systemクラスのgc( )メソッドを使用する。 このメソッドはガーベージコレクタを起動させてほしいとJVMに伝えるだけで、いつ実行させるかはJVM次第である。よくJavaの解説書のこのメソッドの説明に「ガーベージコレクタを実行する」とあるが、これは間違いである。あくまでもできるだけ早くガーベージコレクタを実行させてほしいとJVMに要求するだけである。 |
2.finalize |
C++にはデストラクタがある。デストラクタとはコンストラクタの逆でインスタンスが破壊される時に呼ばれる関数である。しかし、Javaにはデストラクタがない。これは、Javaのインスタンスの破壊はガーベージコレクタに任されていて、インスタンスがいつ破壊されるかわからないためである。しかし、これでは不便なことがある。例えばファイルを開いた場合はファイルをクローズするとか、通信ポートを開いたらそれを閉じるといったメモリー以外のリソースを解放したい場合である。このような場合は、Objectクラスのfinalize( )メソッドをオーバーライドする。finalize( )メソッドはガーベージコレクタによって、メモリが解放される前に呼び出されるメソッドである。このメソッドをオーバーライドしその中でリソースの解放を行う。このfinalize( )メソッドもいつ呼ばれるかは保証されていない。インスタンスが参照されなくなったことが確認され、実際にそのインスタンスが占有していたメモリーを解放される間のどこかで実行されることが保証されているだけである。また、ガーベージコレクタが不要になったインスタンスを発見し、まだfinalize( )メソッドを実行していない場合、SystemクラスのrunFinalize( )メソッドを実行することで、finalize( )の実行を促すことができる。しかしFinalize( )メソッドを実行することでFinalize( )メソッドを実行するのではなく実行するタイミングはJVMの判断に任されている。 |