java - JAXB 解码在一台机器上失败,但在其他机器上失败/也在单元测试中工作

标签 java jaxb

我有一段 JAXB 解码代码,如下所示:

Foo foo = null;
try {
    logger.debug(methodNamePrefix + "xmlString is \n" + xmlString);
    JAXBContext jaxbContext = JAXBContext
                                .newInstance(Foo.class);
    Unmarshaller u = jaxbContext.createUnmarshaller();
    u.setEventHandler(new DefaultValidationEventHandler()); 
    StreamSource streamsource = new StreamSource(new StringReader(xmlString));
    foo = (Foo) u.unmarshal(streamsource);
    sanityCheckDbpAfterUnmarshalling(xmlString, foo);

}catch(Exception e){
    throw new AnalysisNotPossibleException();
}
if (foo==null){
    throw new AnalysisNotPossibleException();
}

这段代码已经工作了几个月,直到最近,在一台机器上,它开始失败。当它失败时,它会吐出一个看似合法的提示——除了同一段代码,具有相同的输入 xmlString,当在另一台机器上运行时,甚至在同一台机器上但在单元测试中运行时,不会提示:

javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"entry"). Expected elements are (none)
        at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:642)
        at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:254)
        at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:249)
        at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.reportUnexpectedChildElement(Loader.java:116)
        at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.childElement(Loader.java:101)
        at com.sun.xml.bind.v2.runtime.unmarshaller.StructureLoader.childElement(StructureLoader.java:243)
        at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext._startElement(UnmarshallingContext.java:478)
        at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.startElement(UnmarshallingContext.java:459)
        at com.sun.xml.bind.v2.runtime.unmarshaller.SAXConnector.startElement(SAXConnector.java:148)

我很确定这是由于该机器的某些本地环境造成的,但我无法弄清楚那是什么。我已经尝试清理 Eclipse 中的所有二进制文件。

我知道这需要调试,并且我不期望得到完整的答案。但如果我能提供更多我可以检查的事情的想法,我将不胜感激。谢谢!

已更新

Foo 类看起来像这样:

@XmlRootElement
public class Foo  implements Serializable{
    private static final long serialVersionUID = -4550266352252980254L;

    @XmlElement
    private HashMap<String, SomeProperty> mapAllPortletProperty =
            new HashMap<String, SomeProperty>();
    ...

XML 字符串如下所示

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<foo>
    <mapAllPortletProperty>
        <entry>
            <key>Portlet 6262</key>
            <value>
                <apIdStrAtBirth>4536</apIdStrAtBirth>               
                ...

第二次更新

感谢迄今为止的所有帮助。这帮助我思考这些 两个方面:

  1. 资源泄漏? StreamSourceStringReader 正在保留 完成解码后的一些资源?
  2. 线程安全?参见这篇关于“JAXB creating context and marshallers cost”的帖子

对于#1,我检查过似乎没有资源泄漏。 我还有一个压力测试程序,它做了很多整理工作。我没有观察到该程序的内存占用量不断增加。

对于#2,我重写了我的代码,以便对于每个需要的类 为了进行解码,我的代码仅实例化 JAXBContext 一次。

不幸的是,有了上述新的见解,我仍然无法 找到问题的根本原因。欢迎更多见解!

最佳答案

经过多次调试,找到了问题的原因。

在我的一个文件夹中,有两个与 JAXB 相关的 JAR 文件:

$ find . -name "jaxb*" -exec ls -l {} \;
-rwx------+ 1 leecy None 89967 Mar 19  2014 ./war/WEB-INF/lib/jaxb-api-2.1.jar
-rwx------+ 1 leecy None 876610 Mar 19  2014 ./war/WEB-INF/lib/jaxb-impl-2.1.13.jar

我认为 JVM 附带的 JAXB 引用实现(我使用的是 Oracle/Sun 的 JDK 1.7.0_51),我们不需要这些额外的 JAR 文件,是吗?它们的存在实际上可能会混淆我的程序并导致加载不同的 JAXBContextImpl 。由于某种原因,此类实现无法解码 XML 文件。

受到此启发blog post ,我让我的程序在实例化后打印出实现的确切类名,我得到了这些结果:

如果我删除了额外的 JAR 文件,我的程序会打印出这一行,并且解码将起作用:

getJcMap(): Just instantiated an JAXBContext: class com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl

如果我把它们留在里面,我的程序会打印这个,并且解码将会失败:

getJcMap(): Just instantiated an JAXBContext: class com.sun.xml.bind.v2.runtime.JAXBContextImpl

这解释了为什么问题仅发生在具有特定项目文件夹的特定计算机上,而不发生在其他环境中。

所以我删除了那些额外的 JAR 文件,问题就解决了!

谢谢大家!节日快乐!

关于java - JAXB 解码在一台机器上失败,但在其他机器上失败/也在单元测试中工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41308531/

相关文章:

java - 从ip地址获取html

java - 热衷于摆脱 swig 包装器中的内存分配/释放?

java - JPA 持久性属性干扰 JAXB

java - 在 Akka 中初始化一个 actor,Play 2.4.2

java - 如何避免 Java 方法中的无用返回?

java - 如何在 BlueJ 中为 ArrayList 输入参数?

java - 无论如何将构造函数参数传递给 JAXB 适配器?

java - Jaxb2Marshaller 无法以线程安全的方式解码非 XmlRoot 元素

java - @XmlElementWrapper 和@XmlElement 无法使用 Jackson 进行反序列化

jaxb - Jersey Restful Web 服务 - MessageBodyProviderNotFoundException