XStream
  1. XStream
  2. XSTR-690

Broken deserialization of singleton references using custom readResolve method returning null

    Details

    • Type: Bug Bug
    • Status: Closed Closed
    • Priority: Major Major
    • Resolution: Cannot Reproduce
    • Affects Version/s: 1.3.1
    • Fix Version/s: 1.4.2
    • Component/s: Converters
    • Labels:
      None
    • JDK version and platform:
      Sun 1.6.0_23

      Description

      We have our own abstract Enum base class implementation for which a custom readResolve method has been implemented that ensures that singleton instances are returned upon deserialization (with our without XStream) that looks like this:

      public Object readResolve() throws java.io.ObjectStreamException {
      try

      { Class clazz = getClassWithFields(); Field f = clazz.getField(_fieldName); return f.get(null); }

      catch (NoSuchFieldException ex)

      { return null; }

      }

      Additionally according readObject and writeObject implementations ensure that the name of the Enum field is (de)serialized:

      private void readObject(java.io.ObjectInputStream in) throws java.io.IOException {
      try

      { _fieldName = (String) in.readObject(); }

      catch (ClassNotFoundException ex)

      { throw new java.io.IOException(ex.getMessage(), ex); }

      }

      Now instead of throwing an Exception in case a value is being read that is not yet available (in case a newer file is being read by an application using an older Enum implementation where the field is not available) we want to initialize such missing Enum values with null - hence null is returned in case the field with the deserialized name cannot be found in readResolve.
      XStream does currently not support this because the AbstractReferenceUnmarshaller does not cache null values (line 63):

      result = super.convert(parent, type, converter);
      if (currentReferenceKey != null && result != null)

      { values.put(currentReferenceKey, result); }

      What's making things worse is that the AbstractReflectionConverter (line 165) calls readResolve after the Object that has been created by default deserialization has already been cached:

      public Object unmarshal(final HierarchicalStreamReader reader, final UnmarshallingContext context)

      { Object result = instantiateNewInstance(reader, context); // after this call the Object returned by readObject has been cached: result = doUnmarshal(result, reader, context); return serializationMethodInvoker.callReadResolve(result); }

      So in case multiple references to the Enum singleton are stored in a file the behaviour is as follows:

      • Upon first deserialization null is returned (as desired) because readResolve is called
      • For all successive references the cached Object deserialized using readObject() is returned

      The attached .xml file contains an ArrayList with multiple Objects referencing such a (non-existing) Enum value.
      While this may seem like a very specific use case it makes me wonder if missing support for null return values in readResolve implementations is really desired.

        People

        • Assignee:
          Jörg Schaible
          Reporter:
          Christian Danner
        • Votes:
          0 Vote for this issue
          Watchers:
          0 Start watching this issue

          Dates

          • Created:
            Updated:
            Resolved: