Javaのメモリリークとは?OutOfMemoryErrorが発生する仕組みとコード例で解説
Javaでは、ガベージコレクション(GC)によってメモリの解放(デストラクタに相当する処理)が自動的に行われます。しかし、コード内でオブジェクトへの参照が残っている場合、そのオブジェクトは解放対象とみなされず、メモリを回収することができません。このような状態が繰り返され、生成・参照されたオブジェクトがまったく使用されなくなると、それらは不要なデータでありながらメモリ上に残り続けます。これがいわゆる「メモリリーク」です。
メモリ使用量が上限を超えると、プログラムは「OutOfMemoryError」というエラーをスローして強制終了します。そのため、不要になったオブジェクトへの参照はすべて削除し、Javaのガベージコレクタが自動的に破棄できるようにすることが常に推奨されています。
以下は、大量のメモリを使用しようとした結果、コンパイラ(JVM)が空き領域を使い果たす様子を示した例です。
サンプルコード
import java.util.Vector;
public class Demo{
public static void main(String[] args){
Vector my_v1 = new Vector(314567);
Vector my_v2 = new Vector(784324678);
System.out.println("This is the last line to be printed");
}
}実行結果
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at java.base/java.util.Vector.<init>(Vector.java:142) at java.base/java.util.Vector.<init>(Vector.java:155) at Demo.main(Demo.java:7)
この例では、Demoというクラスのmainメソッド内で2つのVectorオブジェクトを生成していますが、それぞれに過大な容量を割り当てています。最後のprint文は、プログラムがそこまで到達するかどうかを確認するために記述したものです。実際には、これらのベクターが占有する領域が非常に大きいため、必要なメモリを確保できず、エラーが発生してプログラムは最終行に到達しません。
メモリリークを防ぐポイント
- 不要になったオブジェクトへの参照は明示的に解除する(nullを代入するなど)
- staticフィールドに大きなオブジェクトを保持し続けない
- コレクションから使い終わった要素を適宜削除する
- ヒープ使用状況をプロファイリングツールで定期的に監視する
-
Javaのスレッドセーフなコレクションクラスとは?Stack・Vector・Hashtableなどを解説
スレッドセーフなクラスとは、複数のスレッドから同時に呼び出された場合でも、クラスの内部状態やメソッドの戻り値が常に正しく保たれることが保証されているクラスのことです。Javaにおいてスレッドセーフなコレクションクラスには、Stack、Vector、Properties、Hashtableなどがあります。 Stackクラス JavaのStackクラスは、LIFO(Last In First Out:後入れ先出し)の原理に基づくスタックデータ構造を実装したクラスです。push(要素の追加)、pop(要素の取り出し)、peek(先頭要素の参照)、search(検索)、empty(空判定)など、多彩な
-
Javaプログラムで使用中のメモリ量を確認し、ヒープ不足を防ぐ方法
長時間稼働し、動的メモリを大量に消費するJavaプログラムでは、ヒープ領域のメモリ不足によってOutOfMemoryError(メモリ不足エラー)が発生する可能性があります。これを防ぐためには、プログラム自身がメモリ使用状況を監視し、必要に応じて対処することが有効です。以下のサンプルプログラムでは、Javaプログラムが現在使用しているヒープ領域の使用率を確認できます。ヒープの使用率が90%を超えた場合、ガベージコレクタ(GC)を明示的に呼び出す仕組みになっています。なお、System.gc()はガベージコレクションが完了するまで呼び出し元のスレッドをブロックします。そのため、実際のアプリケーシ