studio - java.lang.outofmemoryerror: gc overhead limit exceeded spark
¿Cuándo es exactamente la JVM que lanza un OutOfMemoryError? (3)
Estamos ejecutando una aplicación Java que a veces se "congela" porque algunos subprocesos usan casi todo el montón. A pesar de que la JVM realiza un GC completo que dura más de 60 segundos, la aplicación nunca muere con OutOfMemoryError.
Leí de la documentación de Java que:
El recolector de rendimiento lanzará una excepción de memoria insuficiente si se está gastando demasiado tiempo en la recolección de basura. Por ejemplo, si la JVM está gastando más del 98% del tiempo total en la recolección de basura y está recuperando menos del 2% del montón, generará una expectativa de falta de memoria.
Me gustaría obtener más información sobre lo que significa este 98% del tiempo (¿cuál es el marco de tiempo?), Y si es posible reducir este valor, es decir, lanzar un OOME si la aplicación está gastando el 90% del tiempo en GC y no puede liberarse Más del 10% del montón.
El objetivo es asegurarse de que la aplicación morirá (en lugar de ejecutar haciendo solo GC) con OOME para que podamos generar un volcado en OOME.
Aquí están los ajustes de memoria y GC que usamos (el sistema operativo es Solaris):
-Xms2048m -Xmx2048m /
-Xmn512m /
-XX:PermSize=256m
-XX:MaxPermSize=256m /
-XX:+UseParNewGC
-XX:ParallelGCThreads=16 /
-XX:+UseConcMarkSweepGC
-XX:+CMSParallelRemarkEnabled /
-XX:+DisableExplicitGC /
-XX:+PrintGC
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps /
-XX:+PrintClassHistogram /
-Xloggc:/gcmonitor.log /
-XX:+HandlePromotionFailure /
-XX:SurvivorRatio=4
-XX:TargetSurvivorRatio=90
-XX:MaxTenuringThreshold=10 /
-XX:+UseTLAB
-XX:TLABSize=32k
-XX:+ResizeTLAB /
-XX:+UseMPSS /
Me gustaría obtener más información sobre lo que significa este 98% del tiempo (¿cuál es el marco de tiempo?)
Responda a esta pregunta: el límite de sobrecarga del GC excedido sugiere que es de 1 minuto.
es posible bajar este valor
Una vez más, analizando la pregunta mencionada anteriormente, parece que puede usar los parámetros GCTimeLimit
y GCHeapFreeLimit
.
Si solo busca forzar a un OOM para obtener el beneficio adicional del volcado de almacenamiento dinámico, ahora puede hacer esto en un proceso Java en ejecución en cualquier momento:
Encuentra el proceso:
jps -v
Forzar un basurero
jmap -dump: file = heap.bin
Luego analice heap.bin en su herramienta de elección.
Tomar un volcado de pila de forma interactiva en OOME o con jmap puede hacer que la JVM se detenga por unos minutos. En general, es más efectivo usar gcore para crear un volcado del núcleo manualmente, luego usar jmap para tomar el volcado del montón del núcleo.
Asignaría más montones, a ver si eso ayuda a mitigar el problema. También tenga cuidado con el ajuste excesivo de GC: en general, los recopiladores tienen excelentes valores predeterminados. Solo recomendaría las opciones después de Xloggc si ha determinado que mejoran significativamente el rendimiento del GC en función de los patrones de asignación / retención de objetos de su aplicación. Los subprocesos del colector paralelo también pueden ser demasiado altos, dependiendo del número de subprocesos de hardware disponibles.
Debería poder determinar el patrón para el uso del montón a partir de los registros del GC y determinar si se trata de un uso rápido por un solo hilo, realizando una operación que agote rápidamente el montón, o un patrón de "fuga" más lento en el que muchos objetos se promocionan el tiempo hace que se contienda con la generación actual, con pocos objetos candidatos para la recolección, los histogramas también ayudarán.
Dicho todo esto, enfocarse en un basurero es definitivamente el camino a seguir. Eclipse MAT es la mejor herramienta de análisis IMO. Este es un buen lugar para comenzar si no lo has usado antes:
http://kohlerm.blogspot.com/2009/07/eclipse-memory-analyzer-10-useful.html