Frequently Asked Questions
- Compatibility
- Serialization
- XML specifics
- Comparison to other products
- Scalability
- Uses of XStream
- Development
Compatibility
Which JDK is required to use XStream?
1.3 or later.
Does XStream behave differently across different JVMs?
XStream has two modes of operation: Pure Java and Enhanced. In pure Java mode, XStream behaves in the same way across different JVMs, however it's features are limited to what reflection allows, meaning it cannot serialize certain classes or fields. In enhanced mode, XStream does not have these limitations, however this mode of operation is not available to all JVMs.
Which JVMs allow XStream to operate in enhanced mode?
Currently on the Sun, Apple, HP, IBM and Blackdown 1.4 JVMs and onwards. Support for BEA JRockit starting with R25.1.0. For all other JVMs, XStream should be used in pure Java mode.
What are the advantages of using enhanced mode over pure Java mode?
Feature | Pure Java | Enhanced Mode |
---|---|---|
Public classes | Yes | Yes |
Non public classes | No | Yes |
Static inner classes | Yes | Yes |
Non-static inner classes | No | Yes |
Anonymous inner classes | No | Yes |
With default constructor | Yes | Yes |
Without default constructor | No | Yes |
Private fields | Yes | Yes |
Final fields | Yes >= JDK 1.5 | Yes |
Are there plans to provide enhanced mode support to other JVMs?
Yes. Let us know which JVM you would like supported.
When should I use XStream not in enhanced mode?
Running XStream in a secured environment can prevent XStream from running in enhanced mode. This is especially true when running XStream in an applet. You may also try to use JavaBean mode as alternative to enhanced or pure Java mode.
Which permissions does XStream need when running with an active SecurityManager?
This depends on the mode XStream is running in. Refer to the SecurityManagerTest for details.
Why does XStream 1.2 no longer read XML generated with XStream 1.1.x?
The architecture in XStream has slightly changed. Starting with XStream 1.2 the HierarchicalStreamDriver implementation is responsible to ensure that XML tags and attributes are valid names in XML, in XStream 1.1.x this responsibility was part of the ClassMapper implementations. Under some rare circumstances this will result in an unreadable XML due to the different processing order in the workflow of such problematic tag names.
You can run XStream in 1.1 compatibility mode though:
XStream xstream = new XStream(new XppDriver(new XStream11XmlFriendlyReplacer())) { protected boolean useXStream11XmlFriendlyMapper() { return true; } };
Serialization
How do I specify that a field should not be serialized?
Make it transient
or specify it with XStream.omitField()
How do I initialize a transient field at deserialization?
XStream uses the same mechanism as the JDK serialization. Example:
class ThreadAwareComponent { private transient ThreadLocal component; // ... private Object readResolve() { component = new ThreadLocal(); return this; } }
XStream is not calling the default constructor during deserialization.
This is, in fact, the same problem as above. XStream uses the same mechanism as the JDK serialization. When using the optimized reflection API, it does not invoke the default constructor. The solution is to implement the readResolve method as above:
class MyExecutor { private Object readResolve() { // do what you need to do here System.out.println("After instantiating MyExecutor"); // at the end returns itself return this; } }
What do serialized collections look like?
Example:
class Person { private String name; private List toys = new ArrayList(); // ... } class Computer { String type; } class Car { String color; } xstream.alias("person", Person.class); xstream.alias("computer", Computer.class); xstream.alias("car", Car.class); Person person = new Person("Joe"); person.addToy(new Computer("apple")); person.addToy(new Computer("spectrum")); person.addToy(new Car("blue")); String xml = xstream.toXML(joe);
Results in:
<person> <name>Joe</name> <toys> <computer> <type>apple</type> </computer> <computer> <type>spectrum</type> </computer> <car> <color>blue</color> </car> </toys> </person>
Note, that it is possible to configure XStream to omit the container element toys using implicit collections.
Do my classes have to implement Serializable if XStream is to serialize them?
No.
Can dynamic proxies be serialized?
Yes.
Can I select the field order in which XStream serializes objects?
Yes. XStream's ReflectionConverter uses the defined field order by default. You can override it by using an specific FieldKeySorter:
SortableFieldKeySorter sorter = new SortableFieldKeySorter(); sorter.registerFieldOrder(MyType.class, new String[] { "firstToSerialize", "secondToSerialize", "thirdToSerialize" }); xstream = new XStream(new Sun14ReflectionProvider(new FieldDictionary(sorter)));
Can CGLIB proxies be serialized?
Only limitedly. A proxy generated with the CGLIB Enhancer is supported, if the proxy uses only one callback and the proxy instance can be generated without additional constructor arguments.
Serialization fails with NoSuchMethodError: net.sf.cglib.proxy.Enhancer.isEnhanced(Ljava/lang/Class;)Z
XStream uses this method to detect a CGLIB-enhanced proxy. Unfortunately the method is not available in the cglib-2.0 version. Since this version is many years old and the method is available starting with cglib-2.0.1, please consider an upgrade of the dependency, it works usually smoothly.
How does XStream deal with newer versions of classes?
- If a new field is added to the class, deserializing an old version will leave the field uninitialized.
- If a field is removed from the class, deserializing an old version that contains the field will cause an exception. Leaving the field in place but declaring it as transient will avoid the exception, but XStream will not try to deserialize it.
- If a class is renamed, aliases can be used to create an abstraction between the name used in XML and the real class name.
- if a field is renamed, this should be treated as adding a field and removing a field.
For more advanced class migrations, you may
- have to do custom pre-processing of the XML before sending it to XStream (for example, with XSLT or DOM manipulations)
- declare new fields as transient
- implement your own converter, that can handle the situation
- add a readResolve() method to your class, that initializes the object accordingly
Future versions of XStream will include features to make these type of migrations easier.
How does XStream cope with isolated class loaders?
Serializing an object graph is never a problem, even if the classes of those objects have been loaded by a different class loader. The situation changes completely at deserialization time. In this case you must set the class loader to use with:
xstream.setClassLoader(yourClassLoader);
Although XStream caches a lot of type related information to gain speed, it keeps those information in tables with weak pointers that should be cleaned by the garbage collector when the types are reloaded.
XML specifics
Why does XStream not respect the encoding in the XML declaration?
XStream architecture is based on IO Readers and Writers, while the XML declaration is the responsibility of XML parsers. XStream uses by default the Xpp3 parser which does ignore the declaration, so you have to provide a Reader with the appropriate encoding yourself if you do not want to read the XML in the default encoding of the current local or you must use a HierarchicalStreamDriver with an XML parser that respects the XML declaration.
Why does XStream not write a XML declaration?
XStream is designed to write XML snippets, so you can embed its output into an existing stream or string. You can write the XML declaration yourself into the Writer before using it to call XStream.toXML(writer).
Why does XStream not write XML in UTF-8?
XStream does no character encoding by itself, it relies on the configuration of the underlying XML writer. By default it uses its own PrettyPrintWriter which writes into the default encoding of the current locale. To write UTF-8 you have to provide a Writer with the appropriate encoding yourself.
Why do field names suddenly have double underscores in the generated XML?
XStream maps Java class names and field names to XML tags or attributes. Unfortunately this mapping cannot be 1:1, since some identifiers of Java contain a dollar sign which is invalid in XML names. Therefore XStream uses an XmlFriendlyReplacer to replace this character with a replacement. By default this replacement uses an underscore and therefore the replacer must escape the underscore itself also. You may provide a different configured instance of the XmlFriendlyReplacer or a complete own implementation, but you must ensure, that the resulting names are valid for XML.
Comparison to other products
How does XStream compare to java.beans.XMLEncoder?
XStream is designed for serializing objects using internal fields, whereas
XMLEncoder is designed for
serializing JavaBeans using public API methods (typically in the form
of getXXX()
, setXXX()
, addXXX()
and removeXXX()
methods.
Scalability
Is XStream thread safe?
Yes. Once the XStream instance has been created and configured, it may be shared across multiple threads allowing objects to be serialized/deserialized concurrently.
Uses of XStream
Is XStream a data binding tool?
No. It is a serialization tool.
Can XStream generate classes from XSD?
No. For this kind of work a data binding tool such as XMLBeans is appropriate.
Development
Why is the XStream source stored in a Subversion repository? What's wrong with CVS?
Subversion is a compelling replacement for CVS. It has been developed building on the experience of CVS and overcomes many of the limitations of CVS while preserving the same ease of use. Among, its advantages, Subversion does not requires connection to the Internet for commands like add, remove, rename, diff and revert. Moreover, operations are truly atomic and directories are treated like files, ie have associated metadata.