Pracujemy nad aplikacją biznesową (1 milion + LOC) opracowaną od ponad 10 lat. Podczas przejścia na JDK8 pojawia się problem z metaprzestrzenną JDK8. Wydaje się, że jest to związane z wersją JaxB wymienioną w pliku com.sun.xml.ws:webservices-rt:1.4 (Metro 1.4). Ze względu na intensywne łączenie w aplikacji i tworzenie starszych klas/instancji za pośrednictwem JaxB nie jest łatwo włączyć stare biblioteki w locie.Stare JaxB i JDK8 Metaspace OutOfMemory Issue
Aktualnie badamy ten problem. Stworzyliśmy przykładowy program, który odtwarza to zachowanie:
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 utrzymuje czystość PermGenSpace. (Symulowane za pomocą 16M PermGen) Memory of run with JDK7
Przy użyciu JDK8 aplikacja działa wolno do wyjątku OOM. VisualVM przechwytuje wyjątek i utrzymuje proces na maksymalnym dostępnym metaprzestrzeni. Nawet tutaj utknął po dłuższej chwili na maksimum. (Symulowane przy użyciu Metaspace 16M) Memory of run with JDK8
Czy ktoś ma jakieś pomysły na to, jak zachować dotychczasowe zachowanie śmieciarki, abyśmy nie mieli problemów z pamięcią? Czy masz jakieś inne pomysły, jak sobie z tym poradzić?
Dzięki.
Edit1: parametry Run JDK7:
-XX:+TraceClassLoading -XX:+TraceClassUnloading -XX:MaxPermSize=16M -XX:PermSize=1M -XX:+UseParallelOldGC -XX:+HeapDumpOnOutOfMemoryError
=> Brak wysypisk sterty są tworzone
parametry wirowania JDK8:
-XX:+TraceClassLoading -XX:+TraceClassUnloading -XX:MaxMetaspaceSize=16M -XX:MetaspaceSize=1M -XX:+UseParallelOldGC -XX:+HeapDumpOnOutOfMemoryError
=> Zrzuty sterty są generowane podczas pracy.
Dostępna pamięć VisualVM nie pokazuje rzeczywistej maksymalnej wartości metaprzestrzennej. Jeśli nie jest ograniczona, metaprzestrzeń stale rośnie, aż pamięć zostanie przekroczona.
edit 2:
Próbowałem wszystkie dostępne śmieciarze dla JDK8. Wszystkie mają ten sam problem.
edit 3:
Rozwiązywanie przez wymianę bibliotekami jest trudny w naszej rzeczywistej aplikacji z powodu dużego sprzężenia między JAXB & kilku modułów naszej aplikacji. W krótkim okresie potrzebna jest więc poprawka w zakresie działania "śmieciarek". Na dłuższą metę poprawka proppera jest już zaplanowana.
"VisualVM przechwytuje wyjątek i utrzymuje proces" - nigdy nie wiedziałem, że VisualVM może to zrobić. Poza tym, twój zrzut ekranu mówi, że w twoim biegu Java8 Metaspace ma limit "1GB", ale pozostaje na "16 MB", który jest daleki od uruchomienia w kierunku OOME. Metaspace nie wydaje się być zbierany, ale wydaje się, że istnieje prosty, oczywisty powód: w konfiguracji Java 8 * utrzymuje * klasy, ponieważ licznik pozostaje stale w ~ 4300 klasach, podczas gdy w biegu Java 7 , policzono ogromną liczbę ~ 43 000 klas. Tak więc, wydaje się, że klasy są stale odtwarzane ... – Holger
OOM są wyświetlane w debugerze Eclipse podczas działania. Zadanie jest ograniczone parametrami w konfiguracji uruchamiania do 16 MB Metaspace. Nie dotyczy to wystąpienia VisualVM. Więc to mówi inne ilości pamięci. Jeśli zostawiam działającą aplikację bez VisualVM, OOM zatrzymuje proces po prawej stronie w tym samym momencie, w którym proces JDK8 uderza w Metaprzestrzeń 16 MB. Podczas korzystania np. webservices-rt 1.6.1 lub usunięcie tego i przy użyciu implementacji JaxB JDK8 przykładowy program zachowuje stałą ilość 12,5 MB Metasprzestrzeni. Jeśli nie ograniczając pamięci JDK8, wzrośnie, dopóki nie zostanie użyte wszystko. –
Jestem zdezorientowany. Co pokazują zrzuty ekranu? Czy analizujesz swoją aplikację lub VisualVM? – Holger