maxmetaspacesize - java.lang.OutOfMemoryError: espacio de clase comprimido
java.lang.outofmemoryerror: metaspace (2)
Estamos corriendo en java-8-oracle.
Nos mudamos a java8 hace seis meses.
En los últimos días hemos recibido OOME de vez en cuando y no hemos podido identificar ni reproducir el problema.
Cuando ejecutamos una llamada al servidor (tomcat) obtenemos este error en el stacktrace:
java.lang.OutOfMemoryError: Compressed class space
Reiniciar el servidor resuelve el problema. La misma llamada a otro servidor funciona, y también lo hace otra llamada de otro tipo al mismo servidor.
Al mirar en gc.log vemos:
2015-05-27T16:05:42.991+0000: 98774.440: [Full GC (Last ditch collection) 98774.440: [CMS: 575745K->575330K(3495936K), 0.8687777 secs] 575745K->575330K(4107008K), [Metaspace: 97940K->97940K(1396736K)], 0.8696093 secs] [Times: user=0.95 sys=0.00, real=0.88 secs]
2015-05-27T16:05:55.486+0000: 98786.935: [Full GC (Metadata GC Threshold) 98786.935: [CMS: 573414K->578735K(3495936K), 0.9372859 secs] 925046K->578735K(4107008K), [Metaspace: 99428K->99428K(1396736K)], 0.9386626 secs] [Times: user=1.01 sys=0.00, real=0.94 secs]
jstat -gc
regresa:
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
87296.0 87296.0 0.0 3151.4 523776.0 148284.4 3495936.0 574868.5 1395640.0 98066.3 1048576.0 11339.1 12165 636.851 223 116.957
753.808
No veo ningún problema de memoria en el registro jstat o en el registro gc.
Intentar ejecutar jmap -clstats
cuelga:
Attaching to process ID 5110, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.25-b02
finding class loader instances ..
Con oops comprimidos y punteros de clase comprimidos, el espacio disponible para las clases está restringido debido al necesario punteo del puntero. 1GB en tu caso.
Esas son muchas clases, por lo que esto podría indicar que algo en su aplicación está creando muchas clases y nunca las liberará. ¿La recarga de la aplicación tal vez?
Si está seguro de que su aplicación solo necesita tanta memoria para las clases, puede intentar -XX:CompressedClassSpaceSize=...
el límite mediante -XX:CompressedClassSpaceSize=...
o deshabilitar los punteros de clase comprimida a través de -XX:-UseCompressedClassPointers
.
Tenga en cuenta que, por defecto, el espacio de clase comprimido + el montón comprimido (+ algunos gastos generales) no puede superar los 32 GB. Aunque, AIUI, cambiar la alineación del objeto puede superar ese límite aún más.
De lo contrario, debería tomar un volcado dinámico y analizar qué contiene las clases cargadas.
Nos enfrentamos a un problema similar. Lamentablemente, heapdumps no te ayudará ya que las clases no están en el montón, sino en la memoria nativa. Habilítelos en su configuración de JVM para solucionar problemas de las clases cargadas:
-XX: + PrintGCDetails -XX: + TraceClassUnloading -XX: + TraceClassLoading
En nuestro caso, el problema era que JAXBContext.newInstance no era singleton.
Buena suerte, Albert