首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >旧的JaxB和JDK8元空间OutOfMemory问题

旧的JaxB和JDK8元空间OutOfMemory问题
EN

Stack Overflow用户
提问于 2015-10-21 17:28:08
回答 3查看 15.7K关注 0票数 28

我们正在开发一个业务应用程序(1个million+ LOC),它是从10+开始开发的。在切换到JDK8时,我们遇到了JDK8元空间的问题。这似乎与com.sun.xml.ws:webservices-rt:1.4 (Metro 1.4)中引用的JaxB版本有关。由于应用程序中的紧密链接和通过JaxB创建的类/实例的遗留,因此在运行时切换旧的库并不容易。

目前我们正在研究这个问题。我们创建了一个重现此行为的示例程序:

代码语言:javascript
复制
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修复已经计划好了。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-10-30 16:18:44

我们解决了当前的问题,直到能够通过使用以下VM参数修复应用程序中的所有情况:

代码语言:javascript
复制
-Dcom.sun.xml.bind.v2.bytecode.ClassTailor.noOptimize=true

我希望这能帮助其他有类似问题的人……

票数 33
EN

Stack Overflow用户

发布于 2017-02-28 23:37:13

只需使用一次JAXBContext.newInstance()即可为要解组的类创建上下文。否则,它将耗尽您的permgen或metaspace。

票数 3
EN

Stack Overflow用户

发布于 2019-01-16 23:53:09

这就是加里正在讨论的解决方案,它比仅仅设置一个标志要好(因为即使是JAXB guys也建议将其设置为单例……)

代码语言:javascript
复制
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);

可以在here中找到JAXB-564Bug+修复。受scorgar博客的启发

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33255578

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档