ずっと以前の章で、変数のスコープについて話題にしました。変数は 4種類に分類され、それぞれスコープというものがあるという話でした。
一方のインスタンスはどうなっているか、というのがこの章の話題になります。
以下のようなプログラムがあったとします。
Point p; p = new Point(10, 20); p = new Point(50, 60);
このプログラムでは、Point型インスタンスを 2個生成しています。ところが、1個目に生成したインスタンスは、3行目の処理によってどの参照型変数からも参照されないようになってしまいました。
インスタンスには名前がありません。したがって、もうこの 1個目の Point型インスタンスにアクセスする手段はなくなってしまったということになります。
Javaの環境では、このような「もうアクセスできなくなってしまったインスタンス」のリストを収集してします。そして、プログラムがどんどんメモリを消費しメモリ不足に陥った場合に、ガベージコレクションが、この不要になったインスタンスのメモリ領域を解放して、メモリを補充します。
Javaでは、ガベージコレクションの存在によって、作成したインスタンスの後処理を気にしないでプログラムを製作することができます。この点が、C++言語などとの際立った特徴のひとつとなっています。
ソースコードは以下の通り。
X101/X101.java
(14行目に黄色線が表示されますが問題ありません)
import java.awt.Point; /** * ガベージコレクトが発動される例。 * このプログラムは無限ループします。 */ public class X101 { /** * メインメソッド。 * @param args 引数 */ public static void main(String[] args) { Point p; while(true) { p = new Point(10, 20); } } }
実行結果は以下の通り。
(何も出力されないしプログラムも終了しない)
Point型インスタンスを無数に作成していますが、次々と参照を失っていくためガベージコレクションが適宜発動されます。そのため、このプログラムが延々と動作します。
ソースコードは以下の通り。
X102/X102.java
import java.awt.Point; import java.util.ArrayList; import java.util.List; /** * ガベージコレクトが発動されない例。 * このプログラムはエラーを発生します。 */ public class X102 { /** * メインメソッド。 * @param args 引数 */ public static void main(String[] args) { List<Point> points = new ArrayList<Point>(); while(true) { points.add(new Point(10, 20)); } } }
実行結果は以下の通り。
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at X102.main(X102.java:18)
生成した Point型インスタンスは、次々と Listに放り込まれています。そのため、「誰からも参照されなくなったインスタンス」というものが存在しません。結果、ガベージコレクションが発動しようにもできず、OutOfMemoryErrorが発生してしまいました。
なお、パソコンのメモリ搭載量と処理速度によっては、エラーの発生までに長い時間がかかる可能性があります。
以下の記述で、手動でガベージコレクションを実行することができます。
System.gc();
ガベージコレクションは基本的には適当なタイミングで動作するため、リアルタイム処理の最中に発動すると、画面が一瞬止まったりするかもしれません。そんなときには、あらかじめ手動でガベージコレクションをし、メモリを解放することで、状況が改善するかもしれません。