solucion outofmemoryerror maxmetaspacesize exceeded error java jaxb java-8 out-of-memory java-metro-framework

outofmemoryerror - out of memory error java



Old JaxB y JDK8 Metaspace OutOfMemory Issue (2)

Estamos trabajando en una aplicación comercial (1 millón + LOC) desarrollada desde hace más de 10 años. Al cambiar a JDK8 tenemos un problema con el metaspacio de JDK8. Esto parece estar relacionado con la versión JaxB a la que se hace referencia en com.sun.xml.ws:webservices-rt:1.4 (Metro 1.4). Debido a la intensa vinculación en la aplicación y la creación heredada de clases / instancias a través de JaxB, no es sencillo cambiar las bibliotecas antiguas sobre la marcha.

Actualmente estamos investigando este problema. Creamos un programa de muestra que reproduce este comportamiento:

import java.io.ByteArrayInputStream; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Unmarshaller; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement public class X { private static final String XML = "<?xml version=/"1.0/" encoding=/"UTF-8/"?><x test=/"test/" />"; @XmlAttribute String test; public static void main( String[] args ) throws JAXBException, InterruptedException { System.out.println("start"); while ( true ) { JAXBContext jc = JAXBContext.newInstance( X.class ); Unmarshaller unmarshaller = jc.createUnmarshaller(); X object = (X) unmarshaller.unmarshal( new ByteArrayInputStream( XML.getBytes() ) ); System.out.println( object.test ); } } }

JDK7 mantiene el PermGenSpace limpio. (Simulado con 16M PermGen) Memoria de ejecución con JDK7

Al usar JDK8, la aplicación se ejecuta lentamente hasta la excepción OOM. VisualVM captura la excepción y mantiene el proceso en ejecución en el máximo de Metaspace disponible. Incluso aquí se queda atascado después de bastante tiempo corriendo en max. (Simulado con 16M Metaspace) Memoria de ejecución con JDK8

¿Alguien tiene alguna idea de cómo obtener el comportamiento heredado de los recolectores de basura, por lo que no nos encontramos con problemas de memoria? ¿O tienes alguna otra idea de cómo lidiar con este problema?

Gracias.

edit1: Ejecutar parámetros JDK7:

-XX:+TraceClassLoading -XX:+TraceClassUnloading -XX:MaxPermSize=16M -XX:PermSize=1M -XX:+UseParallelOldGC -XX:+HeapDumpOnOutOfMemoryError

=> No se crean volcados de pila

Ejecutar parámetros JDK8:

-XX:+TraceClassLoading -XX:+TraceClassUnloading -XX:MaxMetaspaceSize=16M -XX:MetaspaceSize=1M -XX:+UseParallelOldGC -XX:+HeapDumpOnOutOfMemoryError

=> los volcados de pila se generan mientras se ejecuta.

La memoria disponible de VisualVM no muestra el valor real máximo del metaspace. Si no está limitado, el metaspacio aumenta constantemente hasta que se excede la memoria.

edición 2:

He probado todos los recolectores de basura disponibles para JDK8. Todos tienen el mismo problema.

Edición 3:

Resolver problemas al intercambiar las bibliotecas es difícil en nuestra aplicación real debido al fuerte acoplamiento entre JAXB y varios módulos de nuestra aplicación. Por lo tanto, se necesita una solución para el comportamiento del recolector de basura para el corto plazo. A la larga, la solución adecuada ya está planeada.


JAXBContext.newInstance () se debe usar una vez para crear un contexto para que su clase se pueda desmarcar. Usará su permgen o metaspacio de otra manera.


Resolvimos nuestro problema actual hasta que podemos arreglar todas las incidencias en nuestra aplicación usando el siguiente parámetro de VM:

-Dcom.sun.xml.bind.v2.bytecode.ClassTailor.noOptimize=true

Espero que esto ayude a otros con problemas similares ...