ホームページ  >  記事  >  Java  >  Java の OutOfMemoryError 例外はどのようなシナリオで発生しますか?

Java の OutOfMemoryError 例外はどのようなシナリオで発生しますか?

WBOY
WBOYオリジナル
2023-06-25 19:38:43683ブラウズ

Java はオブジェクト指向プログラミング言語として優れた拡張性と柔軟性を備えていますが、同時にメモリ オーバーフローの問題が発生する可能性があります。この種の問題は、Java のプログラマに OutOfMemoryError 例外を通じてプロンプトを表示します。この記事では、Java での OutOfMemoryError 例外の発生シナリオについて説明します。

  1. 文字列定数プールのオーバーフロー

Java では、String は文字列定数プールに保存されるため、特別なクラスです。プログラムで多数の String 型が使用されると、String 定数プールがオーバーフローしやすくなります。たとえば、次のコード:

public static void main(String[] args) {
  List<String> list = new ArrayList<String>();
  for (int i = 0; ; i++) {
    list.add(String.valueOf(i).intern());
  }
}

このプログラムは継続的に文字列を作成し、リストに追加します。新しい文字列が作成されるたびに、同じ文字列が文字列定数プールにすでに存在するかどうかがチェックされます。すでに存在する場合は文字列への参照が返され、それ以外の場合は新しい文字列オブジェクトが作成され、文字列定数プールに追加されます。上記のコードでは String.valueOf(i).intern() が使用されているため、作成されたすべての文字列は定数プールに配置されます。したがって、文字列がリストに継続的に追加されると、新しい文字列が定数プール内に継続的に作成され、最終的に OutOfMemoryError 例外が発生します。

  1. ヒープ メモリ オーバーフロー

Java のヒープ メモリは、すべての Java スレッドによって共有されるヒープ領域です。プログラムが作成するオブジェクトとそのデータ構造が多すぎると、ヒープ メモリが不足する可能性があります。当然占有されているため、OutOfMemoryError 例外が発生します。たとえば、次のコード:

public class HeapOOM {
  static class OOMObject {
  }

  public static void main(String[] args) {
    List<OOMObject> list = new ArrayList<OOMObject>();
    while (true) {
      list.add(new OOMObject());
    }
  }
}

上記のコードは、継続的に新しい OOMObject オブジェクトを作成し、リストに追加します。 OOMObject は比較的単純であるため、各オブジェクトが使用するヒープ メモリは少ないため、リストは増加し続け、ヒープ メモリは徐々にいっぱいになり、最終的に OutOfMemoryError 例外が発生します。

  1. スタック オーバーフロー

Java では、プログラム実行時の関数呼び出しにスタックの記憶領域が使用され、関数呼び出しごとにスペースが空きます。関数パラメータ、ローカル変数、戻り値などの情報を格納するために使用されます。関数の呼び出しレベルが多すぎると、スタック オーバーフローが発生します。たとえば、次のコード:

public class StackOOM {
  public static void main(String[] args) {
    stackLeak();
  }

  private static void stackLeak() {
    stackLeak();
  }
}

上記のコードでは、 stackLeak() メソッドはそれ自体を継続的に再帰的に呼び出します。これは、関数呼び出しごとにスタック内のスペースが空き、呼び出しの層が多すぎると、占有されるスタック領域がいっぱいであるため、OutOfMemoryError 例外が発生します。

  1. 永続世代のオーバーフロー

Java の永続世代は、クラス、メソッドなどの静的ファイルを格納するために使用されます。 JVM 内のメタデータ ストレージは永続世代に配置されます。アプリケーション内に多数のクラスとメソッドがある場合、永続世代がいっぱいになり、OutOfMemoryError 例外が発生します。たとえば、次のコード:

public class MetaspaceOOM {
  static class OOMObject {
  }

  public static void main(String[] args) {
    List<Class<?>> classes = new ArrayList<Class<?>>();
    while (true) {
      Class<?> c = ClassGenerator.generateClass();
      classes.add(c);
    }
  }
}

class ClassGenerator {
  public static Class<?> generateClass() {
    byte[] classData = createClassData();
    return defineClass(classData);
  }

  private static byte[] createClassData() { ... }

  private static Class<?> defineClass(byte[] classData) {
    return ClassLoader.getSystemClassLoader().defineClass(null, classData, 0, classData.length);
  }
}

上記のコードは、継続的に新しいクラスを作成し、それらをクラスに追加します。ここではカスタム ClassGenerator.generateClass() メソッドを使用してクラスを生成しているため、新しいクラスを継続的に作成すると永続的な世代がいっぱいになり、最終的に OutOfMemoryError 例外が発生します。

概要: OutOfMemoryError 例外は Java の一般的な例外で、通常はプログラムで過剰なメモリ リソースが消費されることが原因で発生します。実際の開発では、OutOfMemoryError 例外が発生した場合、さまざまなシナリオに従ってそれを分析し、ヒープ メモリの増加やコードの最適化などの対応策を講じる必要があります。

以上がJava の OutOfMemoryError 例外はどのようなシナリオで発生しますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。