46

StackOverflowError と OutOfMemoryError の違いと、アプリケーションでそれらを回避する方法は何ですか?

4

11 に答える 11

80

簡潔な答え:

  • OutOfMemoryErrorヒープに関連しています。
  • StackOverflowErrorスタックに関連しています

長い答え:

開始時JVMに、処理に使用できる RAM の量を定義します。JVMこれを処理目的で特定のメモリ位置に分割します。そのうちの 2 つはStack&Heap

メモリ内に大きなオブジェクト (または) 参照オブジェクトがある場合は、 が表示されますOutofMemoryError。オブジェクトへの強い参照がある場合、GC はそのオブジェクトに割り当てられたメモリ領域を消去できません。JVM が新しいオブジェクトにメモリを割り当てようとしたときに、使用可能な十分なスペースOutofMemoryErrorがない場合、必要な量のメモリを割り当てることができないため、スローされます。

回避方法: 不要なオブジェクトを GC で使用できるようにする

すべてのローカル変数とメソッド呼び出しに関連するデータがスタックに置かれます。メソッド呼び出しごとに 1 つのスタック フレームが作成され、ローカルおよびメソッド呼び出し関連のデータがスタック フレーム内に配置されます。メソッドの実行が完了すると、スタック フレームは削除されます。これを再現する 1 つの方法は、メソッド呼び出しに無限ループを使用することですstackoverflow。スタック フレームには呼び出しごとにメソッド データが取り込まれますが、解放 (削除) されないため、エラーが表示されます。

回避方法: メソッド呼び出しが終了していることを確認します (無限ループではありません)。

于 2012-07-11T15:04:47.767 に答える
6

次のような関数があると想像してください

public void f(int x) {
    return f(x + 1);
}

あなたがそれを呼ぶとき、その呼び出しはf何度も何度も呼び出されます。呼び出しごとに、少しの情報がスタックに格納されます。スタックのサイズには制限があるため、。を取得しStackOverflowErrorます。

次のコードを想像してみてください。

for (int i = 1; i > 0; i++)
    vector.add(new BigObject());

ここBigObjectで、は通常のJavaオブジェクトです。ご覧のとおり、ループは終了しません。各割り当てはヒープ上で行われるため、BigObjectsで埋められ、。が取得されますOutOfMemoryError

要点をまとめると:

  • OutOfMemoryErrorオブジェクトを作成しているときにスローされます
  • StackOverflowError関数を呼び出すときにスローされます
于 2012-07-11T15:12:00.170 に答える
3

Java 仮想マシンでは、いくつかのメモリ領域が定義されています。

  1. Java 仮想マシン スタック
  2. ヒープ領域
  3. メソッドエリア
  4. 実行時定数プール
  5. ネイティブ メソッド スタック

上記のすべてにおいて、これらのメモリ領域に割り当てられたメモリが固定されるか、実行時に動的に変更される精度を選択できます。

質問についてOutOfMemoryErrorですが、上記のすべてに当てはまります。OutOfMemoryErrorいずれかのメモリ領域のメモリ拡張が試行されたが、割り当てるのに十分なメモリが利用できない場合にスローされます。

また、 Native Method StackおよびJava Virtual Machine StackStackOverFlowErrorに適用できます。スレッド内の計算で許可されているよりも大きなスタックが必要な場合にスローされます。StackOverFlowError

詳細なリファレンスについては、THE STRUCTURE OF THE JAVA VIRTUAL MACHINEを参照してください。

于 2014-02-12T10:09:20.380 に答える
3

StackOverflowErrorスタックのサイズによって制限される (たとえば、無限再帰を使用して) あまりにも多くのメソッドを別の内部で実行すると発生します。

OutOfMemoryErrorヒープに割り当てられている新しいオブジェクトを割り当てるために JVM がスペースを使い果たしたときに発生します。

于 2012-07-11T15:07:01.353 に答える
1

メモリには、ヒープとスタックの 2 つの領域があります。

  1. スタック メモリは、ローカル変数と関数呼び出しを格納するために使用されます。
  2. ヒープ メモリは、Java でオブジェクトを格納するために使用されます。

関数呼び出しまたはローカル変数を格納するためのメモリがスタックに残っていない場合、JVM はjava.lang.StackOverFlowErrorをスローします。

一方、オブジェクトを作成するためのヒープ領域がなくなった場合、JVM はjava.lang.OutOfMemoryErrorをスローします。

于 2014-03-06T11:34:53.413 に答える
0

StackOverflowError : アプリケーションの再帰が深すぎるためにスタック オーバーフローが発生した場合にスローされます。

OutOfMemoryError : メモリ不足のために Java 仮想マシンがオブジェクトを割り当てることができず、ガベージ コレクタによって使用できるメモリがなくなった場合にスローされます。

于 2012-07-11T15:13:44.170 に答える
0

Javadocsから: JVM スタックに関連する例外的な条件:

1) 新しいスレッドの初期 JVM スタックを作成するために使用できるメモリが不足している場合、JVM は OutOfMemoryError をスローします。

2) スレッド内の計算で、許可されているよりも大きな JVM スタックが必要な場合、JVM は StackOverflowError をスローします。

3) JVM スタックが動的に拡張可能で、拡張が試みられたが、拡張を実行するのに十分なメモリーを使用できない場合、JVM は OutOfMemoryError をスローします。

ヒープに関連する例外的な条件:

1) 自動ストレージ管理システムが利用できる以上のヒープが計算に必要な場合、JVM は OutOfMemoryError をスローします。

于 2015-04-10T14:14:15.053 に答える