我们正在开发一个业务应用程序(1个million+ LOC),它是从10+开始开发的。在切换到JDK8时,我们遇到了JDK8元空间的问题。这似乎与com.sun.xml.ws:webservices-rt:1.4 (Metro 1.4)中引用的JaxB版本有关。由于应用程序中的紧密链接和通过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模拟) Memory of run with JDK7
使用JDK8时,应用程序运行速度很慢,出现了OOM异常。VisualVM捕获异常并使进程在最大可用元空间上运行。即使在这里,它在max上运行了很长一段时间后也会被卡住。(用16M Metaspace模拟) Memory of run with 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的可用内存没有显示实际的最大元空间值。如果不受限制,元空间将不断增加,直到超出内存。
编辑2:
我已经尝试了JDK8所有可用的垃圾收集器。他们都有同样的问题。
编辑3:
在我们的实际应用程序中,很难通过交换库来解决问题,因为JAXB和我们的应用程序的几个模块之间存在严重的耦合。因此,短期内需要对垃圾收集器行为进行修复。从长远来看,propper修复已经计划好了。
https://stackoverflow.com/questions/33255578
复制相似问题