Solución:
Este mensaje significa que, por alguna razón, el recolector de basura está tardando una cantidad excesiva de tiempo (por defecto, el 98% de todo el tiempo de CPU del proceso) y recupera muy poca memoria en cada ejecución (por defecto, el 2% del montón).
Esto significa efectivamente que su programa deja de hacer ningún progreso y está ocupado ejecutando solo la recolección de basura en todo momento.
Para evitar que su aplicación absorba el tiempo de la CPU sin hacer nada, la JVM lanza esto Error
para que tenga la oportunidad de diagnosticar el problema.
Los raros casos en los que he visto que esto sucede es cuando algún código estaba creando toneladas de objetos temporales y toneladas de objetos con referencias débiles en un entorno que ya tenía mucha memoria.
Consulte la guía de ajuste de Java GC, que está disponible para varias versiones de Java y contiene secciones sobre este problema específico:
- La guía de ajuste de Java 11 tiene secciones dedicadas sobre GC excesivo para diferentes recolectores de basura:
- para el coleccionista paralelo
- para el recopilador Concurrent Mark Sweep (CMS)
- no se menciona esta condición de error específica para el recolector Garbage First (G1).
- Guía de ajuste de Java 8 y su sección de GC excesiva
- Guía de ajuste de Java 6 y su sección de GC excesivo.
Citando el artículo de Oracle “Java SE 6 HotSpot[tm] Ajuste de la recolección de basura de la máquina virtual “:
Tiempo de GC excesivo y OutOfMemoryError
El recolector paralelo arrojará un OutOfMemoryError si se gasta demasiado tiempo en la recolección de basura: si más del 98% del tiempo total se dedica a la recolección de basura y se recupera menos del 2% del montón, se lanzará un OutOfMemoryError. Esta característica está diseñada para evitar que las aplicaciones se ejecuten durante un período prolongado de tiempo mientras avanzan poco o ningún progreso porque el montón es demasiado pequeño. Si es necesario, esta función se puede desactivar agregando la opción
-XX:-UseGCOverheadLimit
a la línea de comando.
EDITAR: parece que alguien puede escribir más rápido que yo 🙂
Si está seguro de que no hay pérdidas de memoria en su programa, intente:
- Aumentar el tamaño del montón, por ejemplo
-Xmx1g
. - Habilitar el recopilador de pausa baja concurrente
-XX:+UseConcMarkSweepGC
. - Reutilice los objetos existentes cuando sea posible para ahorrar algo de memoria.
Si es necesario, la verificación de límite se puede desactivar agregando la opción -XX:-UseGCOverheadLimit
a la línea de comando.