1. Información general
En pocas palabras, la JVM se encarga de liberar memoria cuando los objetos ya no se utilizan; este proceso se llama recolección de basura (GC).
El error GC Overhead Limit Exceeded pertenece a la familia de java.lang.OutOfMemoryError y es una indicación de agotamiento de recursos (memoria).
En este artículo rápido, veremos qué causa el error java.lang.OutOfMemoryError: GC Overhead Limit Exceeded y cómo se puede resolver.
2. Error de límite de sobrecarga del GC excedido
OutOfMemoryError es una subclase de java.lang.VirtualMachineError ; JVM lo lanza cuando encuentra un problema relacionado con la utilización de recursos. Más específicamente, el error ocurre cuando la JVM pasó demasiado tiempo realizando la recolección de basura y solo pudo recuperar muy poco espacio de almacenamiento dinámico.
Según los documentos de Java, de forma predeterminada, la JVM está configurada para generar este error si el proceso de Java pasa más del 98% de su tiempo haciendo GC y cuando solo se recupera menos del 2% del montón en cada ejecución. En otras palabras, esto significa que nuestra aplicación ha agotado casi toda la memoria disponible y el recolector de basura ha pasado demasiado tiempo tratando de limpiarla y ha fallado repetidamente.
En esta situación, los usuarios experimentan una lentitud extrema de la aplicación. Ciertas operaciones, que generalmente se completan en milisegundos, requieren más tiempo. Esto se debe a que la CPU está utilizando toda su capacidad para la recolección de basura y, por lo tanto, no puede realizar ninguna otra tarea.
3. Error en acción
Veamos un fragmento de código que arroja java.lang.OutOfMemoryError: GC Overhead Limit Exceeded.
Podemos lograr eso, por ejemplo, agregando pares clave-valor en un bucle no terminado:
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())); } } }
Cuando se invoca este método, con los argumentos JVM como -Xmx100m -XX: + UseParallelGC (el tamaño del montón de Java se establece en 100 MB y el algoritmo GC es ParallelGC), obtenemos un error java.lang.OutOfMemoryError: GC Overhead Limit Exceeded . Para comprender mejor los diferentes algoritmos de recolección de basura, podemos consultar el tutorial Java Garbage Collection Basics de Oracle.
Vamos a tener una java.lang.OutOfMemoryError: Límite excedido Overhead GC error muy rápidamente mediante la ejecución siguiente comando desde la raíz del proyecto:
mvn exec:exec
También debe tenerse en cuenta que, en algunas situaciones, es posible que encontremos un error de espacio de pila antes de encontrar el error GC Overhead Limit Exceeded .
4. Solución del error de límite de gastos generales excedido del GC
La solución ideal es encontrar el problema subyacente de la aplicación examinando el código en busca de fugas de memoria.
Deben abordarse las siguientes preguntas:
- ¿Cuáles son los objetos de la aplicación que ocupan una gran parte del montón?
- ¿En qué partes del código fuente se asignan estos objetos?
También podemos utilizar herramientas gráficas automatizadas como JConsole que ayuda a detectar problemas de rendimiento en el código, incluido java.lang.OutOfMemoryErrors.
El último recurso sería aumentar el tamaño de la pila modificando la configuración de lanzamiento de la JVM. Por ejemplo, esto proporciona 1 GB de espacio en la pila para la aplicación Java:
java -Xmx1024m com.xyz.TheClassName
Sin embargo, esto no resolverá el problema si hay pérdidas de memoria en el código de la aplicación real. En cambio, pospondremos el error. Por lo tanto, es más recomendable reevaluar el uso de memoria de la aplicación a fondo.
5. Conclusión
En este tutorial, examinamos java.lang.OutOfMemoryError: GC Overhead Limit Exceeded y las razones detrás de él.
Como siempre, el código fuente relacionado con este artículo se puede encontrar en GitHub.