在解组期间从ElementNSImpl到拥有类型的间歇性ClassCastException

时间:2008-12-18 13:39:49

标签: java exception jaxb race-condition unmarshalling

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

然而,由于我们在OSGi平台上运行,其中各个包通过Spring DM异步初始化,因此可能有两个不同的包同时创建其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对象集合(所述解组工作正常BTW)。

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

运行时环境:

  • JAXB 2.1
  • 的OSGi
  • Spring DM
  • 使用包含要编组/解组的类的包的ClassLoader初始化JAXBContext

4 个答案:

答案 0 :(得分:4)

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

JAXBContext.newInstance(MyClass1.class,MyClass2.class, [...]);

答案 1 :(得分:1)

这里建议的方法都没有为我做。但是这解决了我的问题

@XmlAnyElement(lax = true)
public List<Foo> foos;

答案 2 :(得分:0)

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

synchronized (JAXBContext.class) {
    context = JAXBContext.newInstance(packageList, classLoader);
}

答案 3 :(得分:0)

上面的synchronized子句也解决了我的问题,但似乎上下文不应该是局部变量。相反,它应该是实例变量,或静态。我无法重构我的代码我是如何喜欢的,所以我将上下文移动到静态初始化器中,这不是完美的,但似乎有效:

 private static Unmarshaller um;

  static{
    try {
      final JAXBContext ctx = JAXBContext.newInstance(ObjectFactory.class.getPackage().getName());
      um = ctx.createUnmarshaller();
    } catch (final JAXBException e) {
      e.printStackTrace();
    }
  }