Affects Version/s: 1.2.2, 1.3
Fix Version/s: 1.4
Because PureJavaReflectionProvider.instantiateUsingSerialization uses ObjectInputStream to unmarshal objects without a no-argument constructor, it fails when the process happens in OSGi, where the ObjectInputStream class lives in one classloader, but the target class lives in another. This is because Class.forName ignores the contextClassLoader, and uses the caller class' classloader instead. This is really a JDK bug, but since we cannot expect a quick resolution of this problem at the JDK level, a workaround should be used in XStream.
I've encountered the same problem in an OSGi context. The problem is that ObjectInputStream uses some JDK magic called "last defined ClassLoader" which I guess is looking for the topmost non-system classloader on the stack. In our case that would result in the bundle class loader that loaded our bundle which wraps XScale - in any case it's not the one we set with Xstream.setClassLoader.
The solution appears to be to subclass ObjectInputStream and override its resolveClass method: see for example the fourth reply to
For OSGi users a work-around is to add "DynamicImport-Package: *" to the manifest of the bundle that wraps XStream. Of course this undermines the whole dependency control mechanism of OSGi, which is why it is a work-around and not a solution.
Fixed in the PureJavaReflectionProvider, but also in the SerializableConverter, ExternalizableConvrter and CGLIBEnhancedConverter that use also derived ObjectInputStream implementations.
Hi Denis, so what should we do instead? AFAICS there's no possibility to pass the classloader to use into the ObjectInputStream. The situation only happens when the type itself has no default ctor i.e. in consequence we do not have a possibility to recreate such an object anymore. XStream cannot implement a workaround, it was alreaday the workaround. It is limited to the JDK level here.