Unmarshal NullPointerException(带有 JAXB 参考实现)
Posted
技术标签:
【中文标题】Unmarshal NullPointerException(带有 JAXB 参考实现)【英文标题】:Unmarshal NullPointerException (with JAXB reference implementation) 【发布时间】:2014-04-09 04:20:53 【问题描述】:我正在尝试解组 xml 文件,但从 JAXB 库的深处得到了非常奇怪的 NPE。请问您能帮我解决这个问题吗?
这是异常堆栈跟踪的顶部:
java.lang.NullPointerException
at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:258)
at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.handleGenericException(Loader.java:245)
at com.sun.xml.bind.v2.runtime.unmarshaller.Scope.add(Scope.java:123)
at com.sun.xml.bind.v2.runtime.property.ArrayERProperty$ReceiverImpl.receive(ArrayERProperty.java:213)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.endElement(UnmarshallingContext.java:538)
这里是xml类代码:
public class Base
public Base()
public class A extends Base
public A()
public class B extends Base
public B()
@XmlRootElement(name = "test")
@XmlAccessorType
public class TestXml
@XmlElementWrapper(name = "list")
@XmlAnyElement
@XmlJavaTypeAdapter(Adapter.class)
public List<Base> list = new ArrayList<>();
这里是适配器的unmarshal()方法,取自here,稍作修改。
@SuppressWarnings( "unchecked", "rawtypes" )
@Override
public T unmarshal(Element element) throws Exception
if (null == element)
return null;
// 1. Determine the values type from the type attribute.
Class<?> clazz = classLoader.loadClass(element.getAttribute("class"));
// 2. Unmarshal the element based on the value's type.
DOMSource source = new DOMSource(element);
Unmarshaller unmarshaller = getJAXBContext(clazz).createUnmarshaller();
JAXBElement jaxbElement = unmarshaller.unmarshal(source, clazz);
return (T) jaxbElement.getValue();
这里是测试代码:
JAXBContext jaxbContext = JAXBContext.newInstance(TestXml.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
TestXml auth = (TestXml) unmarshaller.unmarshal(new File("testData/test.xml"));
最后,这是我尝试解组的 xml 文件:
<test>
<list>
<item class="my.package.A" />
<item class="my.package.B" />
</list>
</test>
在调试时我发现适配器运行良好,即 unmarshall() 方法总是返回正确类的实例,但之后发生了一些不好的事情。
接下来我发现的是适配器的代码
JAXBElement jaxbElement = unmarshaller.unmarshal(source, clazz);
导致 NPE。当我删除这行代码并将 unmarshall() 的 return 语句替换为
return new A(); //for example
没有发生 NPE。
【问题讨论】:
【参考方案1】:尝试更改此行,
// 1. Determine the values type from the type attribute.
Class<?> clazz = classLoader.loadClass(element.getAttribute("class"));
到,
// 1. Determine the values type from the type attribute.
Class<?> clazz = ClassLoader.loadClass(element.getAttribute("class"));
你的 clazz 变量的原因是空的。
【讨论】:
Aditya,ClassLoader 类没有静态方法 loadClass :-( 我使用 Java 7. 检查你是否使用了java.lang.ClassLoader,因为java7中的ClassLoader有loadClass方法。检查此链接,docs.oracle.com/javase/7/docs/api/java/lang/… 是的,有,但是这个方法不是静态的。 您可以使用 Class.forName 或参考此答案以使用 loadClass 方法加载您的类,***.com/a/18679222/2968614 classLoader 找到类,所以 clazz 变量不为空。是的,我通过这种方式得到这个类加载器:classLoader = Thread.currentThread().getContextClassLoader();【参考方案2】:在另一个解组过程中尝试处理一个解组过程时,我有完全相同的堆栈跟踪。
基本上,在适配器的“解组”方法中,我通过剥离其值并仅保留其属性来构建一个假“标签”。然后,为了正确提取属性,我使用了 jaxb 解组。
错误在 jaxb 中很深,我真的没有在我的代码中看到任何错误。我通过从 2.2.6 迁移到 2.2.11 的最新和最好的 jaxb-core 库解决了我的问题。
【讨论】:
【参考方案3】:这是 JDK 1.7 中包含的 JAXB (2.2.4-2) 版本中的一个错误。
对我来说,在类路径中包含最新版本的 JAXB (2.2.11) 解决了这个问题。
【讨论】:
以上是关于Unmarshal NullPointerException(带有 JAXB 参考实现)的主要内容,如果未能解决你的问题,请参考以下文章
亲測,Eclipse报"An error has occurred,See error log for more details. java.lang.NullPointerExce
亲測,Eclipse报"An error has occurred,See error log for more details. java.lang.NullPointerExce