A logo showing the text blog.marcnuri.com
English
Inicio»Java»java.lang.OutOfMemoryError: GC overhead limit exceeded (ES)

Entradas Recientes

  • Fabric8 Kubernetes Client 7.2.0 está disponible!
  • Conectarse a un servidor MCP con JavaScript y AI SDK
  • Conectarse a un servidor MCP con JavaScript y LangChain.js
  • El Futuro de las Herramientas para Desarrolladores en la era de la IA
  • Conectarse a un servidor Model Context Protocol (MCP) con Java y LangChain4j

Categorías

  • Antiguo
  • Front-end
  • Go
  • Herramientas
  • Industria y negocios
  • Inteligencia Artificial
  • Java
  • JavaScript
  • Operaciones
  • Personal
  • Proyectos personales

Archivos

  • mayo 2025
  • abril 2025
  • marzo 2025
  • febrero 2025
  • enero 2025
  • diciembre 2024
  • noviembre 2024
  • agosto 2024
  • junio 2024
  • mayo 2024
  • abril 2024
  • marzo 2024
  • febrero 2024
  • enero 2024
  • diciembre 2023
  • noviembre 2023
  • octubre 2023
  • septiembre 2023
  • agosto 2023
  • julio 2023
  • junio 2023
  • mayo 2023
  • abril 2023
  • marzo 2023
  • febrero 2023
  • enero 2023
  • diciembre 2022
  • noviembre 2022
  • octubre 2022
  • agosto 2022
  • julio 2022
  • mayo 2022
  • marzo 2022
  • febrero 2022
  • enero 2022
  • diciembre 2021
  • noviembre 2021
  • octubre 2021
  • septiembre 2021
  • agosto 2021
  • julio 2021
  • diciembre 2020
  • octubre 2020
  • agosto 2020
  • junio 2020
  • mayo 2020
  • marzo 2020
  • febrero 2020
  • enero 2020
  • noviembre 2019
  • octubre 2019
  • julio 2019
  • diciembre 2018
  • agosto 2018
  • julio 2018
  • junio 2018
  • mayo 2018
  • marzo 2018
  • febrero 2018
  • noviembre 2017
  • octubre 2017
  • agosto 2017
  • julio 2017
  • enero 2017
  • julio 2016
  • enero 2016
  • diciembre 2015
  • noviembre 2015
  • diciembre 2014
  • marzo 2014
  • febrero 2011
  • junio 2008
  • mayo 2008
  • abril 2008
  • enero 2008
  • junio 2007
  • mayo 2007
  • abril 2007
  • marzo 2007

java.lang.OutOfMemoryError: GC overhead limit exceeded (ES)

2014-12-20 en Java etiquetado Java / JVM / Memoria / Rendimiento por Marc Nuri | Última actualización: 2025-01-19
English version

Introducción

El error java.lang.OutOfMemoryError: GC overhead limit exceeded es un problema común que los desarrolladores de Java encuentran cuando sus aplicaciones consumen demasiado tiempo de CPU en la recolección de basura y este proceso recupera poca memoria. La Máquina Virtual de Java (JVM) desencadena este error cuando pasa más del 98% del tiempo total de ejecución en la recolección de basura, pero recupera menos del 2% de la memoria del heap durante ese período.

Comprender cómo la JVM maneja la recolección de basura y la asignación de memoria es crucial para mantener aplicaciones Java de alto rendimiento.

En este artículo, exploraré las causas del error java.lang.OutOfMemoryError: GC overhead limit exceeded, cómo diagnosticarlo y solucionarlo, y las mejores prácticas para evitarlo en el futuro.

¿Qué causa el error OutOfMemoryError: GC overhead limit exceeded?

El error java.lang.OutOfMemoryError: GC overhead limit exceeded ocurre cuando la JVM pasa demasiado tiempo realizando la recolección de basura y recupera poca memoria.

Este error suele ser causado por una de las siguientes razones:

  1. Fuga de Memoria: Tu aplicación puede tener una fuga de memoria, lo que la lleva a consumir más memoria de la necesaria.
  2. Código Ineficiente: Tu aplicación puede estar utilizando la memoria de forma ineficiente, lo que conduce a una recolección de basura excesiva.
  3. Tamaño del Heap Grande: Si tu aplicación tiene un tamaño de heap grande, la recolección de basura puede tardar más de lo normal en completarse.
  4. Tamaño del Heap Inadecuado: Si tu aplicación tiene un tamaño de heap inadecuado, la recolección de basura puede no ser capaz de recuperar suficiente memoria.

El siguiente fragmento de código muestra un ejemplo de una fuga de memoria que puede provocar el error java.lang.OutOfMemoryError: GC overhead limit exceeded:

MemoryLeak.java
import java.util.ArrayList;
import java.util.List;

public class MemoryLeak {

  // List to store Long objects
  private static final List<Long> longs = new ArrayList<>();

  public static void main(String[] args) {
    // Infinite loop to add Long.MAX_VALUE to the list
    while (true) {
      longs.add(Long.MAX_VALUE);
    }
  }
}

En este ejemplo, Long.MAX_VALUE se agrega repetidamente a la lista, simulando un crecimiento de memoria ilimitado.

Si ejecutamos la clase MemoryLeak con el siguiente comando:

bash
java -Xmx10m -XX:+UseParallelGC MemoryLeak.java

El flag Xmx establece el tamaño máximo del heap en 10MB, y el flag UseParallelGC especifica el Recolector de Basura Paralelo. Considerando que la clase MemoryLeak añade Long.MAX_VALUE a la lista longs en un bucle infinito, la lista crecerá indefinidamente. El recolector de basura intentará recuperar memoria, pero como la lista sigue creciendo y está referenciada por la clase principal, pasará la mayor parte de su tiempo realizando la recolección de basura sin recuperar mucha memoria.

La JVM eventualmente (y rápidamente) se quedará sin memoria y lanzará el error java.lang.OutOfMemoryError: GC overhead limit exceeded:

bash
Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
        at java.base/java.lang.Long.valueOf(Long.java:1204)
        at MemoryLeak.main(MemoryLeak.java:9)
        at java.base/java.lang.invoke.LambdaForm$DMH/0x00007fab38030000.invokeStatic(LambdaForm$DMH)
        at java.base/java.lang.invoke.LambdaForm$MH/0x00007fab3813d400.invoke(LambdaForm$MH)
        at java.base/java.lang.invoke.Invokers$Holder.invokeExact_MT(Invokers$Holder)
        at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invokeImpl(DirectMethodHandleAccessor.java:154)

¿Cómo diagnosticar y solucionar el error OutOfMemoryError: GC overhead limit exceeded?

Para diagnosticar y solucionar el error java.lang.OutOfMemoryError: GC overhead limit exceeded, sigue estos pasos:

  1. Analizar los Heap Dumps: Utiliza una herramienta para el análisis de heap dumps como VisualVM, JProfiler o YourKit para identificar fugas de memoria y uso ineficiente de la memoria.
  2. Optimizar el Código: Identifica y soluciona fugas de memoria, como la retención no intencionada de objetos en colecciones, y asegúrate de un uso eficiente de operaciones intensivas en memoria como el almacenamiento en caché o la creación de objetos.
  3. Ajustar la Recolección de Basura:
    • Ajusta la configuración de la recolección de basura para optimizar el uso de memoria y reducir la sobrecarga de la recolección de basura.
    • Considera utilizar un recolector de basura diferente, como el Recolector de Basura G1 (-XX:+UseG1GC), diseñado para heaps grandes y aplicaciones de baja latencia.
  4. Aumentar el Tamaño del Heap: Si tu aplicación se queda sin memoria, considera aumentar el tamaño del heap para permitir más memoria para la recolección de basura.

Tu proceso debe asegurarse de que la causa raíz del OutOfMemoryError no sea una fuga de memoria o un uso ineficiente de la memoria. Una vez y sólo cuando hayas asegurado que el uso del heap es óptimo y genuino, puedes ajustar la configuración de la recolección de basura o aumentar el tamaño del heap para evitar el error.

Conclusión

El error java.lang.OutOfMemoryError: GC overhead limit exceeded es un problema común en aplicaciones Java que consumen demasiado tiempo de CPU en la recolección de basura. Diagnosticar y solucionar este error implica identificar la causa raíz a través del análisis de heap dumps, resolver ineficiencias de memoria y ajustar la configuración de la JVM para optimizar la recolección de basura y la asignación de memoria. Siguiendo estas buenas prácticas, puedes evitar el error OutOfMemoryError y mejorar el rendimiento y la estabilidad de tus aplicaciones Java.

Referencias

  • Stack Overflow: Error java.lang.OutOfMemoryError: GC overhead limit exceeded
  • Oracle: HotSpot Virtual Machine Garbage Collection Tuning Guide
Twitter iconFacebook iconLinkedIn iconPinterest iconEmail icon

Navegador de artículos
Ejecutar Apache Tomcat y Apache HTTPD en el puerto 80 simultaneamente¿Qué es un Heap Dump en Java?
© 2007 - 2025 Marc Nuri