OutOfMemoryError: Limite de frais généraux du GC dépassée

1. Vue d'ensemble

En termes simples, la JVM s'occupe de libérer de la mémoire lorsque les objets ne sont plus utilisés; ce processus est appelé Garbage Collection (GC).

L' erreur GC Overhead Limit Exceeded appartient à la famille java.lang.OutOfMemoryError et indique un épuisement des ressources (mémoire).

Dans cet article rapide, nous examinerons les causes de l' erreur java.lang.OutOfMemoryError: GC Overhead Limit Exceeded et comment elle peut être résolue.

2. Erreur de dépassement de limite de frais généraux du GC

OutOfMemoryError est une sous-classe de java.lang.VirtualMachineError ; elle est lancée par la JVM lorsqu'elle rencontre un problème lié à l'utilisation des ressources. Plus spécifiquement, l'erreur se produit lorsque la machine virtuelle Java a passé trop de temps à effectuer le nettoyage de la mémoire et n'a pu récupérer que très peu d'espace de tas.

Selon la documentation Java, par défaut, la JVM est configurée pour renvoyer cette erreur si le processus Java passe plus de 98% de son temps à faire GC et lorsque seulement moins de 2% du tas est récupéré à chaque exécution. En d'autres termes, cela signifie que notre application a épuisé presque toute la mémoire disponible et que le garbage collector a passé trop de temps à essayer de le nettoyer et a échoué à plusieurs reprises.

Dans cette situation, les utilisateurs subissent une extrême lenteur de l'application. Certaines opérations, qui se terminent généralement en millisecondes, prennent plus de temps. Cela est dû au fait que le processeur utilise toute sa capacité pour le nettoyage de la mémoire et ne peut donc pas effectuer d'autres tâches.

3. Erreur dans l'action

Regardons un morceau de code qui lance java.lang.OutOfMemoryError: GC Overhead Limit Exceeded.

Nous pouvons y parvenir, par exemple, en ajoutant des paires clé-valeur dans une boucle non terminée:

public class OutOfMemoryGCLimitExceed { public static void addRandomDataToMap() { Map dataMap = new HashMap(); Random r = new Random(); while (true) { dataMap.put(r.nextInt(), String.valueOf(r.nextInt())); } } }

Lorsque cette méthode est invoquée, avec les arguments JVM comme -Xmx100m -XX: + UseParallelGC ( la taille du tas Java est définie sur 100 Mo et l'algorithme GC est ParallelGC), nous obtenons une erreur java.lang.OutOfMemoryError: GC Overhead Limit Exceeded . Pour mieux comprendre les différents algorithmes de récupération de place, nous pouvons consulter le didacticiel sur les bases de la récupération de place Java d'Oracle.

Nous obtiendrons une erreur java.lang.OutOfMemoryError: GC Overhead Limit Exceeded très rapidement en exécutant la commande suivante à partir de la racine du projet:

mvn exec:exec

Il convient également de noter que dans certaines situations, nous pouvons rencontrer une erreur d'espace de tas avant de rencontrer l'erreur GC Overhead Limit Exceeded .

4. Résolution de l'erreur de dépassement de la limite de frais généraux du GC

La solution idéale est de trouver le problème sous-jacent avec l'application en examinant le code pour toute fuite de mémoire.

Les questions suivantes doivent être abordées:

  • Quels sont les objets de l'application qui occupent une grande partie du tas?
  • Dans quelles parties du code source ces objets sont-ils alloués?

Nous pouvons également utiliser des outils graphiques automatisés tels que JConsole qui permet de détecter les problèmes de performances dans le code, y compris java.lang.OutOfMemoryErrors.

Le dernier recours serait d'augmenter la taille du tas en modifiant la configuration de lancement de la JVM. Par exemple, cela donne 1 Go d'espace de stockage pour l'application Java:

java -Xmx1024m com.xyz.TheClassName

Cependant, cela ne résoudra pas le problème en cas de fuites de mémoire dans le code d'application réel. Au lieu de cela, nous reporterons simplement l'erreur. Par conséquent, il est plus conseillé de réévaluer en profondeur l'utilisation de la mémoire de l'application.

5. Conclusion

Dans ce didacticiel, nous avons examiné le java.lang.OutOfMemoryError: GC Overhead Limit Exceeded et les raisons derrière cela.

Comme toujours, le code source lié à cet article se trouve à l'adresse over sur GitHub.