Details
-
Type: Bug
-
Status: Closed
-
Resolution: Fixed
-
Affects Version/s: None
-
Fix Version/s: 1.2.2
-
Component/s: None
-
Labels:None
-
JDK version and platform:Sun_1.5.0_06
Description
I'm trying to use XStream to persist a toolkit-auto-generated Java class to XML and retrieve it when required.
For lucidity, here's a skeletal look of what the generated classes look like:
final public class CHSMTestClass {
public CHSMTestClass()
{ myCluster = new Cluster(); }static public abstract class Parent {
protected Parent(int[] children)
{ children_ = children; } private final int[] children_; // <----------------
}
static public class Cluster extends Parent {
private static int[] children_ = new int[]
; // <----------------
public Cluster()
private final boolean history_;
private String activeChild_;
private String lastChild_;
}
final public Cluster myCluster;
}
Notice that there exist 2 variables called "children_" : the first being a static class variable of Cluster and the other being a private variable of Parent.
XStream generates the following XML file:
<test.mblox.xstream.CHSMTestClass>
<myCluster>
<history_>false</history_>
<children__>
<int>0</int>
<int>1</int>
<int>2</int>
<int>3</int>
</children__>
</myCluster>
</test.mblox.xstream.CHSMTestClass>
Now during unmarshalling, XStream is unable to distinguish the static class member "children_" from a similarly named variable derived from the super class Parent. It tries to set the static class variable and hence the following exceptions:
Exception in thread "main" com.thoughtworks.xstream.converters.ConversionException: Could not set field class test.mblox.xstream.CHSMTestClass$Cluster.children_ : null
---- Debugging information ----
required-type : test.mblox.xstream.CHSMTestClass$Cluster
cause-message : Could not set field class test.mblox.xstream.CHSMTestClass$Cluster.children_ : null
class : test.mblox.xstream.CHSMTestClass
message : Could not set field class test.mblox.xstream.CHSMTestClass$Cluster.children_ : null
path : /test.mblox.xstream.CHSMTestClass/myCluster/children__
cause-exception : com.thoughtworks.xstream.converters.reflection.ObjectAccessException
-------------------------------
at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:45)
at com.thoughtworks.xstream.core.ReferenceByXPathUnmarshaller.convertAnother(ReferenceByXPathUnmarshaller.java:39)
at com.thoughtworks.xstream.converters.reflection.ReflectionConverter.unmarshal(ReflectionConverter.java:103)
at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:38)
at com.thoughtworks.xstream.core.ReferenceByXPathUnmarshaller.convertAnother(ReferenceByXPathUnmarshaller.java:39)
at com.thoughtworks.xstream.core.TreeUnmarshaller.start(TreeUnmarshaller.java:99)
at com.thoughtworks.xstream.core.ReferenceByXPathMarshallingStrategy.unmarshal(ReferenceByXPathMarshallingStrategy.java:12)
at com.thoughtworks.xstream.XStream.unmarshal(XStream.java:552)
at com.thoughtworks.xstream.XStream.unmarshal(XStream.java:540)
at com.thoughtworks.xstream.XStream.fromXML(XStream.java:524)
at test.mblox.xstream.MyXStreamTestClass.deserializeDummyClassObject(MyXStreamTestClass.java:81)
at test.mblox.xstream.MyXStreamTestClass.main(MyXStreamTestClass.java:34)
Caused by: com.thoughtworks.xstream.converters.reflection.ObjectAccessException: Could not set field class test.mblox.xstream.CHSMTestClass$Cluster.children_ : null
at com.thoughtworks.xstream.converters.reflection.Sun14ReflectionProvider.write(Sun14ReflectionProvider.java:102)
at com.thoughtworks.xstream.converters.reflection.Sun14ReflectionProvider.writeField(Sun14ReflectionProvider.java:67)
at com.thoughtworks.xstream.converters.reflection.ReflectionConverter.unmarshal(ReflectionConverter.java:106)
at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:38)
... 11 more
Caused by: java.lang.IllegalArgumentException
at sun.misc.Unsafe.objectFieldOffset(Native Method)
at com.thoughtworks.xstream.converters.reflection.Sun14ReflectionProvider.write(Sun14ReflectionProvider.java:73)
... 14 more
------------
Elementary JUnit test cases attached with this bug report
This problem seems to be related to the FieldDictionary that also registers non serializable fields (transient and static). Due to this, the deserializer tries to access the wrong field.
Here is a patch proposal with an associated test case. The main modification is to skip registration of the non serializable fields (ie static and transient fields) in the FieldDictionary.