Maison  >  Article  >  Java  >  Dans quels scénarios l’exception OutOfMemoryError en Java se produit-elle ?

Dans quels scénarios l’exception OutOfMemoryError en Java se produit-elle ?

WBOY
WBOYoriginal
2023-06-25 19:38:43633parcourir

En tant que langage de programmation orienté objet, Java présente une bonne évolutivité et flexibilité, mais en même temps, des problèmes de débordement de mémoire peuvent survenir. Ce type de problème incite les programmeurs Java à utiliser l'exception OutOfMemoryError. Cet article explorera les scénarios d'occurrence des exceptions OutOfMemoryError en Java.

  1. Débordement du pool constant de chaînes

En Java, String est une classe spéciale car elle est enregistrée dans le pool de constantes String. Lorsqu’un grand nombre de types String sont utilisés dans un programme, il est facile de provoquer un débordement du pool de constantes String. Par exemple le code suivant :

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

Ce programme créera continuellement des chaînes et les ajoutera à la liste. Chaque fois qu'une nouvelle chaîne est créée, il est vérifié si la même chaîne existe déjà dans le pool de constantes String. S'il existe déjà, une référence à la chaîne est renvoyée ; sinon, un nouvel objet chaîne est créé et ajouté au pool de constantes String. Puisque String.valueOf(i).intern() est utilisé dans le code ci-dessus, toutes les chaînes créées seront placées dans le pool de constantes. Par conséquent, lorsque des chaînes sont continuellement ajoutées à la liste, de nouvelles chaînes seront continuellement créées dans le pool constant, conduisant finalement à une exception OutOfMemoryError.

  1. Débordement de mémoire du tas

La mémoire du tas de Java est l'espace du tas partagé par tous les threads Java. Lorsque le programme crée trop d'objets et leurs structures de données, la mémoire du tas peut naturellement être remplie, provoquant une exception OutOfMemoryError. Par exemple, le code suivant :

public class HeapOOM {
  static class OOMObject {
  }

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

Le code ci-dessus créera continuellement de nouveaux objets OOMObject et les ajoutera à la liste. Étant donné que OOMObject est relativement simple, chaque objet occupe seulement moins de mémoire de tas, donc la liste continue de s'allonger et la mémoire de tas se remplit progressivement, conduisant finalement à une exception OutOfMemoryError.

  1. Débordement de pile

En Java, la zone de stockage de la pile est utilisée pour les appels de fonction lors de l'exécution du programme. Chaque appel de fonction ouvrira un espace dans la pile pour stocker les paramètres de fonction, les variables locales et les valeurs de retour. , etc. S'il y a trop de niveaux d'appel de fonction, un débordement de pile se produira. Par exemple, le code suivant :

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

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

Dans le code ci-dessus, la méthode stackLeak() s'appelle continuellement de manière récursive, car chaque appel de fonction ouvrira un espace dans la pile. Trop de niveaux d'appel entraîneront le remplissage de l'espace de la pile. vers le haut, provoquant une exception OutOfMemoryError.

  1. Débordement de génération permanent

La génération permanente de Java est utilisée pour stocker des fichiers statiques, tels que des classes, des méthodes, etc. Le stockage des métadonnées dans la JVM est placé dans la génération permanente. S'il existe un grand nombre de classes et de méthodes dans l'application, la génération permanente sera remplie, provoquant une exception OutOfMemoryError. Par exemple, le code suivant :

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

Le code ci-dessus créera continuellement de nouvelles classes et les ajoutera aux classes. Étant donné que la méthode personnalisée ClassGenerator.generateClass() est utilisée ici pour générer des classes, la création continue de nouvelles classes entraînera le remplissage de la génération permanente, provoquant éventuellement une exception OutOfMemoryError.

Résumé : l'exception OutOfMemoryError est une exception courante en Java, qui est généralement causée par une consommation trop importante de ressources mémoire dans le programme. Dans le développement réel, si vous rencontrez une exception OutOfMemoryError, vous devez l'analyser selon différents scénarios et prendre les mesures correspondantes pour y faire face, comme augmenter la mémoire du tas, optimiser le code, etc.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn