Ancien JAXB et JDK8 Metaspace OutOfMemory

nous travaillons sur une application commerciale (1 million+ LOC) développée depuis plus de 10 ans. En passant à JDK8 nous obtenons un problème avec le metaspace de JDK8. Cela semble lié à la Version JaxB référencée dans com.sun.xml.ws: webservices-rt: 1.4 (Metro 1.4). En raison du lien intense dans l'application et la création de classes/instances via JaxB, il n'est pas simple d'activer à la volée les anciennes bibliothèques.

nous étudions actuellement cette question. Nous avons créé un exemple de programme qui reproduit ce comportement:

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 garde le PermGenSpace propre. (Simulé avec 16M de PermGen) Mémoire de courir avec JDK7

en utilisant JDK8 l'application court lentement à l'exception OOM. Le VisualVM saisit l'exception et maintient le processus en marche sur le maximum de Metaspace disponible. Même ici, il est rangé après un certain temps de course sur max. (Simulé avec 16M de Métaspace) mémoire de run avec JDK8

Quelqu'un a-t-il des idées pour obtenir le comportement des éboueurs, afin que nous ne tombions pas dans ces problèmes de mémoire? Ou avez-vous d'autres idées sur la façon de traiter ce problème?

Merci.

edit1: Exécuter paramètres JDK7:

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

=> Pas de tas dumps sont créés

Exécuter paramètres JDK8:

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

=> les dumps tas sont générés lors de l'exécution.

la mémoire disponible de VisualVM ne montre pas la vraie valeur maximale de metaspace. Si non limité le metaspace augmente constamment jusqu'à ce que la mémoire soit dépassée.

edit 2:

j'ai essayé tous les éboueurs disponibles pour JDK8. Ils ont tous le même problème.

edit 3:

résoudre en échangeant les libs est difficile dans notre application réelle en raison du couplage lourd entre JAXB et plusieurs modules de nos application. Donc, une solution pour le comportement du collecteur d'ordures est nécessaire pour le court terme. Sur le long terme, la réparation propper est déjà prévue.

19
demandé sur The_Gentleman 2015-10-21 12:28:07

2 réponses

nous avons résolu notre problème actuel jusqu'à ce que nous puissions corriger toutes les occurences de notre application en utilisant le paramètre VM suivant:

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

j'espère que cela aidera d'autres personnes avec des problèmes similaires...

22
répondu The_Gentleman 2015-10-30 08:18:43

JAXBContext.newInstance () devrait être utilisé une fois pour créer un contexte pour que votre classe se défasse. Il épuisera votre permgen ou metaspace autrement.

3
répondu Gary Barker 2017-02-28 15:37:12