旧的 JaxB 和 JDK8 元空间 OutOfMemory 问题

我们正在开发一个 10 多年以来开发的业务应用程序(超过 100 万个 LOC).在切换到 JDK8 时,我们遇到了 JDK8 元空间的问题.这似乎与 com.sun.xml.ws:webservices-rt:1.4 (Metro 1.4) 中引用的 JaxB-Version 有关.由于应用程序中的紧密链接以及通过 JaxB 创建类/实例的遗留问题,因此动态切换旧库并不容易.

We are working on a business application (1 million+ LOC) developed since 10+ years. While switching to JDK8 we get an issue with the metaspace of JDK8. This seems to be related to the JaxB-Version referenced in com.sun.xml.ws:webservices-rt:1.4 (Metro 1.4). Because of the intense linking in the application and legacy creation of classes/instances via JaxB it isn't simple to switch on the fly the old libraries.

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

Currently we are researching this issue. We created a sample programm that reproduces this behavior:

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运行的内存

JDK7 keeps the PermGenSpace clean. (Simulated with 16M PermGen) Memory of run with JDK7

使用JDK8应用程序运行缓慢出现OOM异常.VisualVM 捕获异常并保持进程在最大可用元空间上运行.即使在这里,在最大运行一段时间后它也会卡住.(模拟16M元空间)用JDK8运行的内存

Using JDK8 the application runs slowly to the OOM exception. The VisualVM catches the exception and keeps the process running on the maximum of available Metaspace. Even here it gets stucked after quite a while running on max. (Simulated with 16M Metaspace) Memory of run with JDK8

有没有人知道如何获得垃圾收集器的遗留行为,这样我们就不会遇到那些内存不足的问题?或者您有其他想法如何处理这个问题?

Has anyone some ideas how to get the garbage collectors legacy behavior, so we don't run into those out of memory issues? Or do you have any other ideas how to deal with this issue?

谢谢.

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

=> 堆转储在运行时生成.

=> heap dumps are generated while running.

VisualVM 的可用内存不显示真正的最大元空间值.如果没有限制,元空间会不断增加,直到超出内存.

The Memory available of VisualVM does not show the real maximum metaspace value. If not limited the metaspace is constantly increasing untill memory is exceeded.

编辑 2:

我已经为 JDK8 尝试了所有可用的垃圾收集器.他们都有同样的问题.

I have tried all available garbage collectors for JDK8. They all have the same issue.

编辑 3:

由于 JAXB 和我们应用程序的几个模块.因此,短期内需要对垃圾收集器行为进行修复.从长远来看,适当的修复已经计划好了.

Solving by exchanging the libs is difficult in our real application because of heavy coupling between JAXB & several modules of our application. So a fix for the garbage collector behavior is needed for the short run. On the long run the propper fix is already planned.

推荐答案

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

We solved our current issue untill able to fix all occurances in our application by using the following VM-parameter:

-Dcom.sun.xml.bind.v2.bytecode.ClassTailor.noOptimize=true

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

I hope this will help others with similar issues...

相关文章