7

我们遇到了一个非常难以追踪的问题,我们有时会在尝试遍历未编组的对象列表时看到 ClassCastExceptions。重要的是有时,重新启动后特定代码可以正常工作。这似乎指向并发/计时/竞争条件的方向。我可以确认 JAXBContext 以及编组器和解组器都没有同时使用。我们已经通过锁定序列化对它们的访问。

但是,由于我们在 OSGi 平台上运行,其中各个包通过 Spring DM 异步初始化,因此可能有 2 个不同的包同时创建它们的 JAXBContext。

在任何情况下,我都会感谢任何指向解释可能导致这些间歇性ClassCastExceptions 的原因。间歇性很重要,因为它们表明代码本身正常工作,但某些外部因素似乎会影响行为。

这是异常的一个具体示例(注意我删除了公司特定的东西):

Caused by: java.lang.ClassCastException: com.sun.org.apache.xerces.internal.dom.ElementNSImpl cannot be cast to com.foobar.TunnelType
    at com.foobar.NetMonitorImpl.getVpnStatus(NetMonitorImpl.java:180)

第 180 行的方法是一个 for() 构造,循环遍历未编组对象内部的 TunnelType 对象集合(顺便说一句,解组工作正常)。

鉴于实际的对象解组很顺利,JAXB 是否甚至可以在物理上将 ElementNSImpl 对象留在嵌套集合中?

运行环境:

  • JAXB 2.1
  • 操作系统
  • 弹簧DM
  • JAXBContext 使用包含要编组/解组的类的包的 ClassLoader 进行初始化
4

4 回答 4

4

仅当我忘记告诉 JAXBContext 它可能正在处理的所有要编组的类型时,我才会收到此异常。

JAXBContext.newInstance(MyClass1.class,MyClass2.class, [...]);
于 2009-03-22T01:49:33.957 回答
2

这里建议的两种方法都不适合我。然而这解决了我的问题

@XmlAnyElement(lax = true)
public List<Foo> foos;
于 2012-01-10T13:02:34.420 回答
0

出于绝望,我们转向对JAXBContext.class对象进行同步,将其视为某些竞争条件的唯一剩余可能性,至少我们无法再次重现此问题。这是关键代码:

synchronized (JAXBContext.class) {
    context = JAXBContext.newInstance(packageList, classLoader);
}
于 2009-07-21T11:53:21.463 回答
0

上面的同步子句也为我解决了这个问题,但似乎上下文不应该是局部变量。相反,它应该是实例变量或静态变量。我无法按照我的意愿重构我的代码,所以我将上下文移动到静态初始化程序中,这并不完美,但似乎可以工作:

 private static Unmarshaller um;

  static{
    try {
      final JAXBContext ctx = JAXBContext.newInstance(ObjectFactory.class.getPackage().getName());
      um = ctx.createUnmarshaller();
    } catch (final JAXBException e) {
      e.printStackTrace();
    }
  }
于 2011-02-22T17:07:46.390 回答