Alte JaxB und JDK8 Metaspace OutOfMemory-Problem

Arbeiten wir an einem business-Anwendung (1 Mio+ LOC) entwickelt seit 10+ Jahren. Während der Wechsel zu JDK8 bekommen wir ein Problem mit dem metaspace von JDK8. Dies scheint im Zusammenhang mit der JaxB-Version verwiesen, die in com.Sonne.xml.ws:webservices-rt:1.4 (Metro 1.4). Aufgrund der starken Vernetzung in der Anwendung und legacy-Schaffung von Klassen/Instanzen via JaxB es ist nicht einfach, um die Fliegen, die alten Bibliotheken.

Derzeit sind wir zu diesem Thema forscht. Wir erstellten ein sample-programm, das reproduziert dieses Verhalten:

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 hält die PermGenSpace sauber. (Simuliert mit 16 MB PermGen)
Speicher laufen mit JDK7

Mit JDK8 die Anwendung läuft langsam zu den OOM-Ausnahme. Die VisualVM fängt die Ausnahme ab und hält den Prozess auf die maximal zur Verfügung Metaspace. Auch hier wird es hier nach einiger Zeit läuft auf max. (Simuliert mit 16M Metaspace)
Speicher laufen mit JDK8

Hat jemand einige Ideen, wie man den garbage-Kollektoren legacy-Verhalten, also wir laufen nicht in die out of memory Probleme? Oder haben Sie andere Ideen, wie man mit diesem Problem umzugehen?

Dank.

edit1:
Parameter JDK7:

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

=> Keine heap-dumps erstellt werden

Parameter JDK8:

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

=> heap-dumps erzeugt werden, während der Ausführung.

Den Speicher zur Verfügung zu VisualVM nicht die echte maximale metaspace Wert. Wenn nicht, begrenzt der metaspace nimmt ständig zu, bis der Speicher ist überschritten.

edit 2:

Ich habe versucht alle verfügbare garbage-Kollektoren für JDK8. Sie alle haben das gleiche Problem.

edit 3:

Lösung durch den Austausch der libs ist schwierig, in unserer realen Anwendung wegen der starken Kopplung zwischen JAXB & mehrere Module unserer Anwendung. So ein Update für den garbage-collector-Verhalten ist nötig für die kurze Frist. Auf lange Sicht die richtigen fix ist bereits geplant.

  • "VisualVM fängt die Ausnahme ab und hält den Prozess ausführen"—ich wusste nie, dass VisualVM kann das tun. Außerdem, dein screenshot sagt, dass in Ihrem Java8 laufen, der Metaspace hat ein limit von 1GB bleibt aber bei 16MB, die weit entfernt von laufen in Richtung ein OOME. Der Metaspace nicht scheinen, um gesammelt, aber es scheint auch eine einfache, naheliegende Grund: in der Java-8-setup hält es die Klassen, wie der Zähler bleibt konstant bei ~4300 Klassen, in der Erwägung, dass in Java 7 laufen, eine satte Anzahl von ~43 000 Klassen gezählt wurden. So ist es, Klassen zu bekommen scheinen ständig regeneriert...
  • Die Zimmer sind in der Eclipse-debugger während der Ausführung. Die Aufgabe wird begrenzt durch Parameter auf die Konfiguration auszuführen, die zu 16MB Metaspace. Dies gilt nicht für die VisualVM-Instanz. Es sagt also andere Beträge, die der Speicher-Links. Wenn ich die Anwendung ausführen, ohne VisualVM der OOM Stoppt den Prozess, bei Recht gleichen moment der JDK8-Prozeß 16MB Metaspace. Bei der Verwendung von z.B. webservices-rt 1.6.1 oder entfernen Sie dieses und die Verwendung des JDK8 JaxB-Implementierung die Beispiel-programm hält eine Konstante Höhe von 12,5 MB Metaspace. Wenn keine Begrenzung der JDK8-Speicher wird erhöht, bis alle verwendet wird.
  • Ich bin verwirrt. Was die screenshots zeigen? Sind Sie auf der Analyse Ihrer Anwendung oder VisualVM?
  • Die Bilder zeigen die Analyse der Ausführung des Probe-programm. Ich habe die Parameter in der original-Artikel. Es scheint, die VisualVM nicht zeigen, das richtige MaxMetaspace Wert. java.net/jira/browse/VISUALVM-609
  • Sorry, aber deine Erklärung ist immer noch verwirrend. Vor allem der Satz "Bei Verwendung von z.B. webservices-rt 1.6.1 oder entfernen Sie dieses und die Verwendung des JDK8 JaxB-Implementierung die Beispiel-programm hält eine Konstante Höhe von 12,5 MB Metaspace." Wie funktioniert dieses setup unterscheiden sich von den "follow-up", Wenn nicht die Begrenzung JDK8-Speicher wird erhöht, bis alle verwendet wird"? Und Sie sprechen jetzt über "Memory" oder "Meta-Raum"?
  • Wir sprechen auf der PermGen- (JDK7) und auf MetaSpace (JDK8).Wie oben im Beitrag gezeigt, die Speicher-partition ist begrenzt auf 16 MB Speicher (PermGen/MetaSpace) provozieren eine schnelle Einrichtung unserer Ausgabe.Neuere JaxB-Bibliotheken mit der gleichen config hält den Speicher innerhalb dieses dünnen Grenzen und benötigt keine zusätzlichen Flächen pro iteration der Schleife.Auf unseren Systemen ist dies auf manchen zeitgesteuerte Prozesse mit dem Effekt, dass die JDK7 funktioniert perfekt mit weniger als 2GB(gesamte Dienstleistung) RAM zur Verfügung steht und dass die Verwendung von JDK8 das gleiche system braucht 6+GB RAM, nachdem Sie einige Tage laufen!Die Probe hat das gleiche Verhalten.
  • Erste von allen, der PermGen und MetaSpace sind verschiedene Dinge, und es ist falsch, zu glauben, die Begrenzung der gleichen Größe war die gleiche Sache zu tun. Zweitens, wenn Sie schon wissen, dass "neuere JaxB-Bibliotheken" löst dein problem, dann wissen Sie bereits, wo ist das Problem und wie es zu lösen. Wenn die alten Bibliotheken haben ein Speicher-Leck, ersetzen Sie Sie, anstatt zu spielen mit JVM-Optionen...
  • Der Speicherverlust tritt nur bei der Verwendung von Java 8, im Fall von Java 7 die GC reinigt unbenutzte Klassen ohne Probleme. Wie bereits in der Frage einschalten der JaxB-version ist nur lebensfähig auf lange Sicht für uns.

Schreibe einen Kommentar