Мы работаем над бизнес-приложением (1 млн. + LOC), разработанным с 10 лет. При переключении на JDK8 мы получаем проблему с метаспасом JDK8. Это похоже на JaxB-версию, указанную в com.sun.xml.ws:webservices-rt:1.4 (Metro 1.4). Из-за интенсивной связи в приложении и унаследованного создания классов/экземпляров через JaxB не так просто переключать на лету старые библиотеки.
В настоящее время мы изучаем эту проблему. Мы создали примерную программу, которая воспроизводит это поведение:
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 сохраняет PermGenSpace в чистоте. (Имитируется с 16M PermGen) Память запуска с JDK7
Используя JDK8, приложение работает медленно с исключением OOM. VisualVM ловит исключение и удерживает процесс в максимальном объеме доступного Metaspace. Даже здесь он застрял после довольно продолжительного хода на макс. (Имитировано с 16M Metaspace) Память запуска с JDK8
Есть ли у кого-нибудь какие-то идеи о том, как получить унаследованное поведение сборщиков мусора, поэтому мы не сталкиваемся с этими проблемами? Или у вас есть другие идеи, как справиться с этой проблемой?
Спасибо.
edit1: Параметры запуска JDK7:
-XX:+TraceClassLoading -XX:+TraceClassUnloading -XX:MaxPermSize=16M -XX:PermSize=1M -XX:+UseParallelOldGC -XX:+HeapDumpOnOutOfMemoryError
= > Не создаются свалки кучи
Параметры запуска JDK8:
-XX:+TraceClassLoading -XX:+TraceClassUnloading -XX:MaxMetaspaceSize=16M -XX:MetaspaceSize=1M -XX:+UseParallelOldGC -XX:+HeapDumpOnOutOfMemoryError
= > В процессе работы генерируются дампы кучи.
Память, доступная для VisualVM, не показывает реального максимального значения метапоса. Если не ограничено, метапас будет постоянно увеличиваться до тех пор, пока память не будет превышена.
edit 2:
Я попробовал все доступные сборщики мусора для JDK8. У всех у них такая же проблема.
edit 3:
Решения об обмене библиотеками сложны в нашем реальном приложении из-за сильной связи между JAXB и несколькими модулями нашего приложения. Поэтому для краткосрочного запуска требуется исправление поведения сборщика мусора. В долгосрочной перспективе исправление исправления уже запланировано.