Details
-
Type: Bug
-
Status: Closed
-
Resolution: Fixed
-
Affects Version/s: None
-
Fix Version/s: 1.2
-
Component/s: None
-
Labels:None
Description
XStream seems to have trouble with CGLIB proxies based on real classes. See following effect for a proxy extending HashMap, where the ObjectName element gets lost, that is stored in the HashMap of the DelegatingHandler:
public class DelegatingHandler implements InvocationHandler, Serializable {
private final Object delegate;
public DelegatingHandler(Object delegate)
{ this.delegate = delegate; }public Object invoke(Object obj, Method method, Object[] args) throws Throwable
{ return method.invoke(delegate, args); }}
/**
- @throws Exception
*/
public void testCGLib() throws ExceptionUnknown macro: { final Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(HashMap.class); enhancer.setInterfaces(new Class[]{Map.class}); enhancer.setCallback(new DelegatingHandler(new HashMap())); final Map orig = (Map)enhancer.create(); orig.put("ObjectName", new ObjectName("domain}
A really bad coincidence happen for CGLIB proxies of real classes. A CGLIB class proxy will delegate all method calls, but represents still a complete instance of the original class. If this class is Serializable and has a readObject/writeObject methods two things may happen:
a) any direct access to a field will reference the element in the proxied instance
b) any indirect access will be delegated by the proxy
This may leed to the situation, that the values written into the stream might be from different objects.
In the above case the proxied HashMap writes a size of 0 into the stream and writes afterwards the elements of the delegate. Since those elements are written again later, XStream creates a reference. Unfortunately the readObject method of the HashMap will recognize, that it has no elements and just skip all the written values ... and all references will suddenly point to nothing.