StackOverflowError と OutOfMemoryError の違いと、アプリケーションでそれらを回避する方法は何ですか?
11 に答える
簡潔な答え:
OutOfMemoryError
ヒープに関連しています。StackOverflowError
スタックに関連しています
長い答え:
開始時JVM
に、処理に使用できる RAM の量を定義します。JVM
これを処理目的で特定のメモリ位置に分割します。そのうちの 2 つはStack
&Heap
メモリ内に大きなオブジェクト (または) 参照オブジェクトがある場合は、 が表示されますOutofMemoryError
。オブジェクトへの強い参照がある場合、GC はそのオブジェクトに割り当てられたメモリ領域を消去できません。JVM が新しいオブジェクトにメモリを割り当てようとしたときに、使用可能な十分なスペースOutofMemoryError
がない場合、必要な量のメモリを割り当てることができないため、スローされます。
回避方法: 不要なオブジェクトを GC で使用できるようにする
すべてのローカル変数とメソッド呼び出しに関連するデータがスタックに置かれます。メソッド呼び出しごとに 1 つのスタック フレームが作成され、ローカルおよびメソッド呼び出し関連のデータがスタック フレーム内に配置されます。メソッドの実行が完了すると、スタック フレームは削除されます。これを再現する 1 つの方法は、メソッド呼び出しに無限ループを使用することですstackoverflow
。スタック フレームには呼び出しごとにメソッド データが取り込まれますが、解放 (削除) されないため、エラーが表示されます。
回避方法: メソッド呼び出しが終了していることを確認します (無限ループではありません)。
次のような関数があると想像してください
public void f(int x) {
return f(x + 1);
}
あなたがそれを呼ぶとき、その呼び出しはf
何度も何度も呼び出されます。呼び出しごとに、少しの情報がスタックに格納されます。スタックのサイズには制限があるため、。を取得しStackOverflowError
ます。
次のコードを想像してみてください。
for (int i = 1; i > 0; i++)
vector.add(new BigObject());
ここBigObject
で、は通常のJavaオブジェクトです。ご覧のとおり、ループは終了しません。各割り当てはヒープ上で行われるため、BigObject
sで埋められ、。が取得されますOutOfMemoryError
。
要点をまとめると:
OutOfMemoryError
オブジェクトを作成しているときにスローされますStackOverflowError
関数を呼び出すときにスローされます
Java 仮想マシンでは、いくつかのメモリ領域が定義されています。
- Java 仮想マシン スタック
- ヒープ領域
- メソッドエリア
- 実行時定数プール
- ネイティブ メソッド スタック
上記のすべてにおいて、これらのメモリ領域に割り当てられたメモリが固定されるか、実行時に動的に変更される精度を選択できます。
質問についてOutOfMemoryError
ですが、上記のすべてに当てはまります。OutOfMemoryError
いずれかのメモリ領域のメモリ拡張が試行されたが、割り当てるのに十分なメモリが利用できない場合にスローされます。
また、 Native Method StackおよびJava Virtual Machine StackStackOverFlowError
に適用できます。スレッド内の計算で許可されているよりも大きなスタックが必要な場合にスローされます。StackOverFlowError
詳細なリファレンスについては、THE STRUCTURE OF THE JAVA VIRTUAL MACHINEを参照してください。
StackOverflowError
スタックのサイズによって制限される (たとえば、無限再帰を使用して) あまりにも多くのメソッドを別の内部で実行すると発生します。
OutOfMemoryError
ヒープに割り当てられている新しいオブジェクトを割り当てるために JVM がスペースを使い果たしたときに発生します。
メモリには、ヒープとスタックの 2 つの領域があります。
- スタック メモリは、ローカル変数と関数呼び出しを格納するために使用されます。
- ヒープ メモリは、Java でオブジェクトを格納するために使用されます。
関数呼び出しまたはローカル変数を格納するためのメモリがスタックに残っていない場合、JVM はjava.lang.StackOverFlowErrorをスローします。
一方、オブジェクトを作成するためのヒープ領域がなくなった場合、JVM はjava.lang.OutOfMemoryErrorをスローします。
StackOverflowError : アプリケーションの再帰が深すぎるためにスタック オーバーフローが発生した場合にスローされます。
OutOfMemoryError : メモリ不足のために Java 仮想マシンがオブジェクトを割り当てることができず、ガベージ コレクタによって使用できるメモリがなくなった場合にスローされます。
Javadocsから: JVM スタックに関連する例外的な条件:
1) 新しいスレッドの初期 JVM スタックを作成するために使用できるメモリが不足している場合、JVM は OutOfMemoryError をスローします。
2) スレッド内の計算で、許可されているよりも大きな JVM スタックが必要な場合、JVM は StackOverflowError をスローします。
3) JVM スタックが動的に拡張可能で、拡張が試みられたが、拡張を実行するのに十分なメモリーを使用できない場合、JVM は OutOfMemoryError をスローします。
ヒープに関連する例外的な条件:
1) 自動ストレージ管理システムが利用できる以上のヒープが計算に必要な場合、JVM は OutOfMemoryError をスローします。