メモリー・リークの一般的な兆候の1つは、java.lang.OutOfMemoryError
例外です。通常、このエラーは、Javaヒープにオブジェクトを割り当てるための十分な空間がないときにスローされます。この場合、ガベージ・コレクタによって新しいオブジェクトを格納するための空間を確保することも、ヒープをこれ以上拡張することもできません。また、このエラーは、Javaクラスのロードをサポートするための十分なネイティブ・メモリーがないときにスローされる場合もあります。ガベージ・コレクションの実行に過剰な時間が消費され、メモリーがほとんど解放されていない場合、まれにjava.lang.OutOfMemoryError
がスローされることがあります。
java.lang.OutOfMemoryError
例外がスローされるときに、スタック・トレースも出力されます。
java.lang.OutOfMemoryError
例外は、ネイティブ割当てを満たすことができないとき(たとえば、スワップ空間が少ない場合)に、ネイティブ・ライブラリ・コードによってスローされることもあります。
OutOfMemoryError
例外を診断する最初の手順は、その例外の原因を突き止めることです。スローされた理由が、Javaヒープがいっぱいであるからなのか、それともネイティブ・ヒープがいっぱいであるからなのかを調べます。原因を見つけることができるように、例外テキストの最後に詳細なメッセージが含まれています(次の例外を参照)。
それ以外の場合、特に長期にわたって稼動するアプリケーションでは、このメッセージはアプリケーションが誤ってオブジェクトへの参照を保持しているため、オブジェクトのガベージ・コレクションができないことを示している可能性があります。これは、Java言語ではメモリー・リークに相当します。注意: アプリケーションによって呼び出されたAPIが誤ってオブジェクト参照を保持している可能性もあります。
このエラーのもう1つの潜在的な原因は、ファイナライザを過度に使用するアプリケーションで発生します。クラスにfinalize
メソッドがある場合、そのタイプのオブジェクトの空間はガベージ・コレクション時に再利用されません。かわりに、ガベージ・コレクション後にファイナライズ用のキューにオブジェクトが入れられ、後でファイナライズが実行されます。Oracle Sunの実装では、ファイナライザはファイナライズ・キューを提供するデーモン・スレッドによって実行されます。ファイナライザ・スレッドがファイナライズ・キューを処理しきれなかった場合は、Javaヒープがいっぱいになる可能性があり、このタイプのOutOfMemoryError
例外がスローされます。この状況を発生させるシナリオの1つは、アプリケーションが優先度の高いスレッドを作成しているため、ファイナライザ・スレッドがファイナライズ・キューを処理する速度よりキューの増加速度の方が速くなっている場合です。
java.lang.OutOfMemoryError
がスローされます。この例外は通常、Javaヒープに新しい割当て用の空き領域がわずかしかなく、ライブ・データの容量をほとんど格納できないためにスローされます。「GC Overhead limit exceeded」
のjava.lang.OutOfMemoryError例外は、コマンド行フラグ-XX:-UseGCOverheadLimit
を使用すると無効にできます。OutOfMemoryError
がスローされます。MetaSpace
」という詳細のjava.lang.OutOfMemoryError
例外がスローされます。クラス・メタデータに使用できるメタスペース容量は、コマンド行に指定するMaxMetaSpaceSize
パラメータにより制限されます。クラス・メタデータに必要なネイティブ・メモリー容量がMaxMetaSpaceSize
を超過すると、MetaSpace
詳細とともにjava.lang.OutOfMemoryError
例外がスローされます。MaxMetaSpaceSize
が設定されている場合は、その値を増やしてください。MetaSpace
は、Javaヒープと同じアドレス空間から割り当てられます。Javaヒープのサイズを減らすと、MetaSpace
に使用できる領域が増えます。このトレードオフが成り立つのは、Javaヒープに余分な空き領域がある場合のみです。次に示す「Out of swap space」詳細メッセージの「処置」を参照してください。OutOfMemoryError
例外であるように見えます。しかし、ネイティブ・ヒープからの割当てが失敗し、ネイティブ・ヒープが枯渇寸前になっている可能性があるときに、Java HotSpot VMコードはこの見かけ上の例外を報告します。このメッセージは、失敗した要求のサイズ(バイト数)とメモリー要求の理由を示しています。通常、その理由は割当ての失敗を報告するソース・モジュールの名前になりますが、場合によっては実際の理由になることもあります。このタイプのOutOfMemoryError
例外がスローされた場合は、オペレーティング・システムのトラブルシューティング・ユーティリティを使用して、問題をより詳しく診断する必要がある場合があります。様々なオペレーティング・システムで利用可能なツールの詳細は、「オペレーティング・システムのネイティブ・ツール」を参照してください。
UseCompressedOops
を使用)。これはコマンド行フラグUseCompressedClassPointers
で制御されます(デフォルトの場合)。UseCompressedClassPointers
が使用されている場合、クラス・メタデータに使用できる領域量はCompressedClassSpaceSize
の容量で固定されます。UseCompressedClassPointers
に必要な領域がCompressedClassSpaceSize
を超える場合、「Compressed class space」
という詳細のjava.lang.OutOfMemoryErrorがスローされます。CompressedClassSpaceSize
を増やして、UseCompressedClassPointers
をオフにしてください。注意: CompressedClassSpaceSize
の許容サイズには制限があります。たとえば、-XX: CompressedClassSpaceSize=4g
が許容制限を超えると、次のようなメッセージが表示されます。
CompressedClassSpaceSize
of 4294967296 is invalid; must be between 1048576 and 3221225472. (CompressedClassSpaceSizeの4294967296は無効です。1048576から3221225472の間に設定する必要があります。)
注意: クラス・メタデータには複数の種類(klass
メタデータやその他のメタデータ)があります。CompressedClassSpaceSize
によって制限された領域に格納されるのは、klass
メタデータのみです。その他のメタデータはMetaspace
に格納されます。
OutOfMemoryError
例外がスローされた場合は、OSのネイティブ・ユーティリティを使用して、問題をより詳しく診断する必要がある場合があります。様々なオペレーティング・システムで利用可能なツールの詳細は、「オペレーティング・システムのネイティブ・ツール」を参照してください。