java 在解组期间从 ElementNSImpl 到自己的类型的间歇性 ClassCastException
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/377865/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Intermittent ClassCastException from ElementNSImpl to own type during unmarshalling
提问by Boris Terzic
We are experiencing an exceedingly hard to track down issue where we are seeing ClassCastExceptions sometimeswhen trying to iterate over a list of unmarshalled objects. The important bit is sometimes, after a reboot the particular code works fine. This seems to point in the direction of concurrency/timing/race condition. I can confirm that neither the JAXBContext, nor the marshallers and unmarshallers are being used concurrently. We've gone as far as serializing access to them through locking.
我们遇到了一个非常难以追踪的问题,我们有时会在尝试遍历未编组对象列表时看到 ClassCastExceptions 。重要的是有时,重新启动后特定代码工作正常。这似乎指向并发/时序/竞争条件的方向。我可以确认 JAXBContext 以及编组器和解组器都没有同时使用。我们已经通过锁定序列化了对它们的访问。
However, since we run on an OSGi platform where individual bundles are getting initialized asynchronously through Spring DM it can be that 2 different bundles are creating their JAXBContext at the same time.
但是,由于我们在 OSGi 平台上运行,其中单个包通过 Spring DM 异步初始化,因此可能有 2 个不同的包同时创建它们的 JAXBContext。
In any case I would appreciate any pointers towards an explanation for what could cause these intermittentClassCastExceptions. The intermittent is important since they indicate that the code itself is normally working fine but that some external factor seems to influence the behaviour.
在任何情况下,我都会感谢任何有关可能导致这些间歇性ClassCastExceptions的解释的指针。间歇性很重要,因为它们表明代码本身通常工作正常,但某些外部因素似乎影响了行为。
Here's a specific example of the exception (note I removed the company specific stuff):
这是异常的一个具体示例(注意我删除了公司特定的内容):
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)
That method at line 180 is a for() construct looping over a Collection of TunnelType objects inside of an unmarshalled object (said unmarshalling works fine BTW).
第 180 行的那个方法是一个 for() 构造,它在未编组对象内的 TunnelType 对象集合上循环(顺便说一下,解组工作正常)。
Given that the actual object unmarshalling went fine, is it even physically possible for JAXB to leave ElementNSImpl objects inside of nested collections?
鉴于实际的对象解组进行得很顺利,JAXB 在物理上是否有可能将 ElementNSImpl 对象留在嵌套集合中?
Runtime environment:
运行环境:
- JAXB 2.1
- OSGi
- Spring DM
- The JAXBContext is initialised with the ClassLoader of the bundle containing the classes to be marshalled/unmarshalled
- JAXB 2.1
- 操作系统
- 弹簧 DM
- JAXBContext 使用包含要编组/解组的类的包的 ClassLoader 进行初始化
采纳答案by Boris Terzic
Out of despair we turned to synchronizing on the JAXBContext.classobject, seeing this as the only remaining possibility for some race condition and at least we have not been able to reproduce this issue again. Here's the critical code:
出于绝望,我们转向同步JAXBContext.class对象,将其视为某些竞争条件的唯一剩余可能性,至少我们无法再次重现此问题。这是关键代码:
synchronized (JAXBContext.class) {
context = JAXBContext.newInstance(packageList, classLoader);
}
回答by ivan_ivanovich_ivanoff
I get this exception ONLY when I forget to tell JAXBContext about ALL to-be-marshalled types it could be dealing with.
仅当我忘记告诉 JAXBContext 它可能处理的所有待编组类型时,我才会收到此异常。
JAXBContext.newInstance(MyClass1.class,MyClass2.class, [...]);
回答by Johan Sj?berg
Neither of the approaches suggested here did it for me. However this resolved my problem
这里建议的方法都不适合我。然而这解决了我的问题
@XmlAnyElement(lax = true)
public List<Foo> foos;
回答by jon077
The synchronized clause above resolved the issue for me as well, but it seems like the context should not be a local variable. Instead it should be an instance variable, or a static. I wasn't able to refactor my code how I'd like it, so instead I moved the context into a static initializer, which isn't perfect, but seems to work:
上面的 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();
}
}

