Heim  >  Artikel  >  Java  >  In welchen Szenarien tritt die OutOfMemoryError-Ausnahme in Java auf?

In welchen Szenarien tritt die OutOfMemoryError-Ausnahme in Java auf?

WBOY
WBOYOriginal
2023-06-25 19:38:43633Durchsuche

Als objektorientierte Programmiersprache verfügt Java über eine gute Skalierbarkeit und Flexibilität, gleichzeitig kann es jedoch zu Speicherüberlaufproblemen kommen. Diese Art von Problem fordert Programmierer in Java durch die OutOfMemoryError-Ausnahme auf. In diesem Artikel werden die Auftretensszenarien von OutOfMemoryError-Ausnahmen in Java untersucht.

  1. Überlauf des String-Konstantenpools

In Java ist String eine besondere Klasse, da sie im String-Konstantenpool gespeichert wird. Wenn in einem Programm eine große Anzahl von String-Typen verwendet wird, kann es leicht zu einem Überlauf des String-Konstantenpools kommen. Zum Beispiel der folgende Code:

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

Dieses Programm erstellt kontinuierlich Zeichenfolgen und fügt sie der Liste hinzu. Bei jeder Erstellung eines neuen Strings wird geprüft, ob derselbe String bereits im String-Konstantenpool vorhanden ist. Wenn es bereits vorhanden ist, wird ein Verweis auf den String zurückgegeben; andernfalls wird ein neues String-Objekt erstellt und dem String-Konstantenpool hinzugefügt. Da String.valueOf(i).intern() im obigen Code verwendet wird, werden alle erstellten Zeichenfolgen im Konstantenpool abgelegt. Wenn der Liste fortlaufend Zeichenfolgen hinzugefügt werden, werden daher kontinuierlich neue Zeichenfolgen im Konstantenpool erstellt, was schließlich zu einer OutOfMemoryError-Ausnahme führt.

  1. Heap-Speicherüberlauf

Der Heap-Speicher von Java ist der von allen Java-Threads gemeinsam genutzte Heap-Speicherplatz. Wenn das Programm zu viele Objekte und deren Datenstrukturen erstellt, kann es sein, dass der Heap-Speicher voll ist, was zu einer OutOfMemoryError-Ausnahme führt. Zum Beispiel der folgende Code:

public class HeapOOM {
  static class OOMObject {
  }

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

Der obige Code erstellt kontinuierlich neue OOMObject-Objekte und fügt sie der Liste hinzu. Da OOMObject relativ einfach ist, belegt jedes Objekt nur weniger Heap-Speicher, sodass die Liste weiter zunimmt und der Heap-Speicher allmählich aufgefüllt wird, was schließlich zu einer OutOfMemoryError-Ausnahme führt.

  1. Stapelüberlauf

In Java wird der Speicherbereich des Stapels für Funktionsaufrufe verwendet, wenn das Programm ausgeführt wird. Jeder Funktionsaufruf öffnet einen Platz im Stapel zum Speichern von Funktionsparametern, lokalen Variablen und Rückgabewerten usw. Informationen. Wenn die Funktion zu viele Aufrufebenen hat, kommt es zu einem Stapelüberlauf. Zum Beispiel der folgende Code:

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

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

Im obigen Code ruft sich die Methode stackLeak() kontinuierlich rekursiv auf, da jeder Funktionsaufruf einen Platz im Stapel öffnet. Zu viele Aufrufebenen führen dazu, dass der Stapelplatz gefüllt wird up, was zu einer OutOfMemoryError-Ausnahme führt.

  1. Überlauf der permanenten Generation

Die permanente Generation von Java wird zum Speichern statischer Dateien wie Klassen, Methoden usw. verwendet. Der Metadatenspeicher in der JVM wird in der permanenten Generation platziert. Wenn die Anwendung eine große Anzahl von Klassen und Methoden enthält, wird die permanente Generation überfüllt, was zu einer OutOfMemoryError-Ausnahme führt. Zum Beispiel der folgende Code:

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);
  }
}

Der obige Code erstellt kontinuierlich neue Klassen und fügt sie zu Klassen hinzu. Da hier die benutzerdefinierte ClassGenerator.generateClass()-Methode zum Generieren von Klassen verwendet wird, führt das kontinuierliche Erstellen neuer Klassen dazu, dass die permanente Generation aufgefüllt wird, was schließlich zu einer OutOfMemoryError-Ausnahme führt.

Zusammenfassung: Die OutOfMemoryError-Ausnahme ist eine häufige Ausnahme in Java, die normalerweise dadurch verursacht wird, dass zu viele Speicherressourcen im Programm verbraucht werden. Wenn Sie in der tatsächlichen Entwicklung auf eine OutOfMemoryError-Ausnahme stoßen, müssen Sie diese anhand verschiedener Szenarien analysieren und entsprechende Maßnahmen ergreifen, um damit umzugehen, z. B. Erhöhen des Heap-Speichers, Optimieren des Codes usw.

Das obige ist der detaillierte Inhalt vonIn welchen Szenarien tritt die OutOfMemoryError-Ausnahme in Java auf?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn