Details
-
Type: Bug
-
Status: Closed
-
Priority: Critical
-
Resolution: Fixed
-
Affects Version/s: 1.4.6
-
Fix Version/s: 1.4.7
-
Component/s: Converters
-
Labels:None
Description
Hi. I recently upgraded my application from XStream 1.4.5 to 1.4.6. It just blew up immediately with a NullPointerException.
Although I still does not have a small test case for this (I will create one in the next few days, if you wish), I got a stacktrace and could use it to find the source of the problem.
In XStream 1.4.5, the implementation of the class com.thoughtworks.xstream.converters.reflection.ReflectionConverter used to simply return true in the method canConvert(Class), which means that it accepted null as an argument.
This method changed in XStream 1.4.6, and the new implementation pass the argument down to the canAccess(Class) type without checking for null. The methods down the stack don't check for null either, which results in a NullPointerException in the com.thoughtworks.xstream.converters.reflection.FieldDictionary class, at line 127, when the code tries to determine the superclass of the null argument.
This is the stacktrace:
java.lang.NullPointerException
at com.thoughtworks.xstream.converters.reflection.FieldDictionary.buildMap(FieldDictionary.java:127)
at com.thoughtworks.xstream.converters.reflection.FieldDictionary.fieldOrNull(FieldDictionary.java:113)
at com.thoughtworks.xstream.converters.reflection.PureJavaReflectionProvider.getFieldOrNull(PureJavaReflectionProvider.java:193)
at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.canAccess(AbstractReflectionConverter.java:61)
at com.thoughtworks.xstream.converters.reflection.ReflectionConverter.canConvert(ReflectionConverter.java:23)
at com.thoughtworks.xstream.core.DefaultConverterLookup.lookupConverterForType(DefaultConverterLookup.java:56)
at com.thoughtworks.xstream.mapper.AttributeMapper.getLocalConverterFromItemType(AttributeMapper.java:74)
at com.thoughtworks.xstream.mapper.AttributeMapper.getConverterFromItemType(AttributeMapper.java:96)
at com.thoughtworks.xstream.mapper.MapperWrapper.getConverterFromItemType(MapperWrapper.java:107)
at com.thoughtworks.xstream.mapper.EnumMapper.getConverterFromItemType(EnumMapper.java:75)
at com.thoughtworks.xstream.mapper.MapperWrapper.getConverterFromItemType(MapperWrapper.java:107)
at com.thoughtworks.xstream.mapper.LocalConversionMapper.getConverterFromItemType(LocalConversionMapper.java:64)
at com.thoughtworks.xstream.mapper.MapperWrapper.getConverterFromItemType(MapperWrapper.java:107)
at com.thoughtworks.xstream.mapper.MapperWrapper.getConverterFromItemType(MapperWrapper.java:107)
at com.thoughtworks.xstream.mapper.MapperWrapper.getConverterFromItemType(MapperWrapper.java:107)
at com.thoughtworks.xstream.mapper.MapperWrapper.getConverterFromItemType(MapperWrapper.java:107)
at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter$1.visit(AbstractReflectionConverter.java:111)
at com.thoughtworks.xstream.converters.reflection.PureJavaReflectionProvider.visitSerializableFields(PureJavaReflectionProvider.java:137)
at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.doMarshal(AbstractReflectionConverter.java:93)
at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.marshal(AbstractReflectionConverter.java:83)
at com.thoughtworks.xstream.core.TreeMarshaller.convert(TreeMarshaller.java:70)
at com.thoughtworks.xstream.core.TreeMarshaller.convertAnother(TreeMarshaller.java:58)
at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.marshallField(AbstractReflectionConverter.java:250)
at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter$2.writeField(AbstractReflectionConverter.java:226)
at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter$2.<init>(AbstractReflectionConverter.java:189)
at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.doMarshal(AbstractReflectionConverter.java:135)
at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.marshal(AbstractReflectionConverter.java:83)
at com.thoughtworks.xstream.core.TreeMarshaller.convert(TreeMarshaller.java:70)
at com.thoughtworks.xstream.core.TreeMarshaller.convertAnother(TreeMarshaller.java:58)
at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.marshallField(AbstractReflectionConverter.java:250)
at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter$2.writeField(AbstractReflectionConverter.java:226)
at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter$2.<init>(AbstractReflectionConverter.java:189)
at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.doMarshal(AbstractReflectionConverter.java:135)
at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.marshal(AbstractReflectionConverter.java:83)
at com.thoughtworks.xstream.core.TreeMarshaller.convert(TreeMarshaller.java:70)
at com.thoughtworks.xstream.core.TreeMarshaller.convertAnother(TreeMarshaller.java:58)
at com.thoughtworks.xstream.core.TreeMarshaller.convertAnother(TreeMarshaller.java:43)
at com.thoughtworks.xstream.core.TreeMarshaller.start(TreeMarshaller.java:82)
at com.thoughtworks.xstream.core.AbstractTreeMarshallingStrategy.marshal(AbstractTreeMarshallingStrategy.java:37)
at com.thoughtworks.xstream.XStream.marshal(XStream.java:994)
at com.thoughtworks.xstream.XStream.marshal(XStream.java:983)
at com.thoughtworks.xstream.XStream.toXML(XStream.java:956)
<... My own classes here ...>
Actually I am very interested in a test case, because I don't understand, how it can happen with this stack trace in first place. It crashes looking for the converter of a field, but a field's type is never null.
The ReflectionConverter itself could on top of it never handle the "null" type, returning true was a bald lie. However, it should not cause a NPE in canConvert.