The*_*man 23 java java-metro-framework jaxb out-of-memory java-8
我们正在开发自10年以来开发的业务应用程序(100万+ LOC).在切换到JDK8时,我们遇到了JDK8的元空间问题.这似乎与com.sun.xml.ws:webservices-rt:1.4(Metro 1.4)中引用的JaxB-Version有关.由于应用程序中的密切链接以及通过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 );
}
}
}
Run Code Online (Sandbox Code Playgroud)
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的可用内存未显示实际的最大元空间值.如果不受限制,则元空间不断增加,直到超过内存.
编辑2:
我已经为JDK8尝试了所有可用的垃圾收集器.他们都有同样的问题.
编辑3:
由于JAXB与我们应用程序的几个模块之间存在大量耦合,因此在我们的实际应用中通过交换库进行解决是很困难的.因此,短期内需要修复垃圾收集器行为.从长远来看,已经计划好了.
The*_*man 27
我们解决了当前的问题,直到使用以下VM参数来修复应用程序中的所有问题:
-Dcom.sun.xml.bind.v2.bytecode.ClassTailor.noOptimize=true
Run Code Online (Sandbox Code Playgroud)
我希望这能帮助其他有类似问题的人......
这是 Gary 正在谈论的解决方案,这比仅仅设置一个标志更好(因为即使是JAXB 的人也建议将其设置为单例......)
private static Map<class<?>, JAXBContext> contextStore = new ConcurrentHashMap<class<?>, JAXBContext>();
...
protected static JAXBContext getContextInstance(Class<?> objectClass) throws JAXBException{
JAXBContext context = contextStore.get(objectClass);
if (context==null){
context = JAXBContext.newInstance(objectClass);
contextStore.put(objectClass, context);
}
return context;
}
//using it like this:
JAXBContext context = getContextInstance(objectClass);
Run Code Online (Sandbox Code Playgroud)
JAXB-564 Bug + 修复可以在这里找到。灵感来自scorgar早已消失的博客