maxmetaspacesize - java8 "java.lang.OutOfMemoryError: Metaspace"
java.lang.outofmemoryerror: metaspace jboss (3)
Supongo que puede crear el problema con la misma solicitud (Conjunto de solicitudes) durante un período de tiempo. Es bueno que haya definido MaxMetaspaceSize, de lo contrario, la aplicación utilizará la memoria nativa hasta que se agote. Pero voy a comenzar con los siguientes pasos:
- Compruebe si su número de clases que se cargan en JVM sigue creciendo para la misma solicitud cuando lo envía al servidor varias veces. Si es así, es posible que esté creando clases dinámicas que podrían causar un crecimiento en las clases cargadas en el metaspacio. Bien, cómo verificar el número de clases cargadas, puede usar visualvm para conectarse al servidor utilizando JMX o ejecutar localmente para simular. Mencionaré los pasos para la conexión local, pero para la conexión remota de JMX, debe agregar los siguientes parámetros de la JVM a la aplicación e iniciarla y la conexión remota en el puerto 9999 y con -XX: + UnlockDiagnosticVMOptions.
-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9999 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -XX:+UnlockDiagnosticVMOptions
Una vez que tenga el visualvm (jvisualvm) conectado a la JVM, haga clic en el monitor y luego vea el número de clases cargadas. Allí puede controlar el montón, así como el metaspacio. Pero agregaré las otras herramientas para monitorear de cerca el metaspacio.
- Además, una vez que esté conectado a la jvm, es posible que desee tomar una instantánea del montón y descubrir las clases cargadas utilizando OQL. Entonces, antes de tomar un volcado de almacenamiento dinámico, detenga las solicitudes al servidor, de modo que no detecte ningún código de ejecución / solicitud en vuelo y sus objetos asociados, pero no es necesario. Entonces, después de ejecutar el mismo conjunto de solicitudes varias veces, dentro de visualvm, en el espacio "monitor", haga clic en "Volcar volcado" en la parte superior derecha ". Luego, abra / cargue la instantánea, y verá la opción para la consola OQL. Y Verá algunas consultas OQL predefinidas en el panel inferior derecho bajo el análisis de permgen. Ejecute la consulta denominada "histograma de clases cargadas del cargador de clases", supongo que le dará el recuento de las clases cargadas por cada cargador de clases. Puede usarlo para averiguar qué cargador de clases Está cargando clases.
seleccione map (sort (map (heap.objects (''java.lang.ClassLoader''), ''{loader: it, count: it.classes.elementCount}''), ''lhs.count <rhs.count''), ''toHtml (it) + "
"'')
Pero la consulta sobre la llamada "clase cargada del cargador de clases" será lenta, lo que en realidad mostrará las clases cargadas por cada cargador de clases.
select { loader: cl,
classes: filter(map(cl.classes.elementData, ''it''), ''it != null'') }
from instanceof java.lang.ClassLoader cl
- A continuación, intente rastrear el crecimiento en el área de metaspacio. Ahora usaremos jconsole y algo nuevo que java tiene: jmc (java mission control). Puede usar jconsole para conectarse a jvm (local o remoto) y, una vez que esté conectado, vaya a la pestaña de memoria y podrá monitorear el crecimiento no acumulativo allí, que debería tener el caché de metaespacio y código y el espacio de clase comprimido. Y ahora conecta
jmc
para conectarse a la máquina virtual y luego, una vez que esté conectado, haga clic en "Comandos de diagnóstico" en el JMC que se encuentra en la parte superior derecha. Dado que hemos habilitado UnlockDiagnosticVMOptions, GC.class_stats podría ejecutarse. Es posible que desee ejecutarlo con mostrar todas las columnas e imprimir en csv. Entonces el comando se verá como:
GC.class_stats -all=true -csv=true
Y luego puede comparar las estadísticas de clase en diferentes períodos y descubrir qué clases están causando problemas (crecimiento del metaspacio) o qué clases tienen información relacionada (método / datos de método) en el metaspacio. Cómo analizar las salidas de csv recopiladas en un momento: bueno, tomaría ese csv y lo cargaría en dos tablas similares (que representan a csv) en una base de datos o en algún otro lugar para comparar las salidas de GC.class_stats csv donde puedo ejecutar algunos SQL o Cualquier otra herramienta de análisis. Eso daría una mejor idea de lo que está creciendo exactamente en el metaspacio. Las estadísticas de la clase GC tienen las siguientes columnas:
Índice, Super, InstSize, InstCount, InstBytes, Espejo, KlassBytes, K_secondary_supers, VTAB, Itab, OopMap, IK_methods, IK_method_ordering, IK_default_methods, IK_default_vtable_indices, IK_local_interfaces, IK_transitive_interfaces, IK_fields, IK_inner_classes, IK_signers, class_annotations, class_type_annotations, fields_annotations, fields_type_annotations, methods_annotations, method_parameter_annotations, methods_type_annotations, methods_default_annotations, anotaciones, Cp, CpTags, CpCache, CpRefMap, CpAl.lp.p.P.P.L.P.P.P.P.P.
Espero eso ayude. También parece que el error puede estar en Java 8 si no causa ninguna fuga en 1.7.
Además, las clases no se descargarán del metacespacio si alguien mantiene alguna referencia al cargador de clases. Si sabe que se supone que sus cargadores de clases deben ser GCed y nadie debe mantener la referencia a su cargador de clases, puede volver al volcado de pila en visualvm y hacer clic en la instancia del cargador de clases y hacer clic con el botón derecho para encontrar la "raíz GC más cercana". Usted que está sosteniendo la referencia a los cargadores de clases.
Después de cambiar nuestra aplicación java (servicios que se ejecutan en Tomcat) JRE de Java 7 a Java 8, comenzamos a ver java.lang.OutOfMemoryError: Metaspace
después de ejecutar algunos días con alto volumen de tráfico.
El uso del montón estaba bien. Metaspace salta después de un tiempo en que se ejecutó el mismo flujo de código durante las pruebas de rendimiento.
¿Cuáles podrían ser las posibles causas del problema de la memoria del metaspacio?
La configuración actual es:
-server -Xms8g -Xmx8g -XX:MaxMetaspaceSize=3200m -XX:+UseParNewGC
-XX:+UseConcMarkSweepGC -XX:MaxGCPauseMillis=1000
-XX:+DisableExplicitGC -XX:+PrintGCDetails
-XX:-UseAdaptiveSizePolicy -XX:SurvivorRatio=7 -XX:NewSize=5004m
-XX:MaxNewSize=5004m -XX:MaxTenuringThreshold=12
-XX:CMSInitiatingOccupancyFraction=75
-XX:+UseCMSInitiatingOccupancyOnly -XX:+PrintFlagsFinal
-XX:+PrintGCDateStamps -XX:+PrintTenuringDistribution
-XX:+PrintGCCause -XX:+PrintAdaptiveSizePolicy
-XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=3 -XX:GCLogFileSize=200M
También la aplicación tiene un uso intensivo de la reflexión. También usamos un cargador de clases personalizado. Todos ellos trabajaban bien en java 7.
también si algunos implementan automáticamente como Tomcat, NO guarde copias de seguridad en tomcat / webapps, de lo contrario, posiblemente intente cargar la copia de seguridad y colisione con esos recursos.
tuvimos un problema similar y la causa raíz fue que los archivos de clase 60K se están cargando en la memoria del metaspacio, pero nada se está descargando.
-Dcom.sun.xml.bind.v2.bytecode.ClassTailor.noOptimize=true
https://issues.apache.org/jira/browse/CXF-2939
Espero que esto ayude.