views:

69

answers:

1

I have written my Container<T> class which backups its T items in several collections -- primary one is List<T>, others are various maps with data derived from items, mostly for optimized search.

Class looks like this:

class Container<T> implements Serializable {
    private static final long serialVersionUID = 1L;

    private final List<T> items = Lists.newArrayList();
    private final Map<...> map1 = Maps.newHashMap();
    private final Map<...> map2 = Maps.newHashMap();
}

Standard serialization works like a charm, but maps do not need to be serialized. I tried to set maps as transient and use readObject() in this way:

class Container<T> implements Serializable {
    private static final long serialVersionUID = 1L;

    private final List<T> items = Lists.newArrayList();
    private transient Map<...> map1;
    private transient Map<...> map2;

    public Container() {
        initContainer();
    }

    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        in.defaultReadObject();
        initContainer();
    }

    private void initContainer() {
        map1 = Maps.newHashMap();
        map2 = Maps.newHashMap();
        // prepare data in maps
        for (T item: items) {
            map1.put(...);
            map2.put(...);
        }
    }
}

Simple test with ObjectOutputStream.writeObject() and ObjectInputStream.readObject() again works. But when I integrate Container to real application where is this class serialized and deserialized as a part of other complex classes (Wicket Page in fact), strange things happens.

I did some debugging and here are my findings:

  • serialization of Container with (n) items has done OK
  • deserialization of Container has done OK
  • deserialization of each T item is called only (n-1) times (by counting calls to its readObject() method)
  • in containerInit() had List<T> correct (n) number of items, but one of them (that one for which is not called deserialization) is in very strange state - all fields have null value - and my code here throws NPE

Questions:

  • What state has that strange object after deserialization (it is existing but without readObject() call and with null in all fields)?
  • Maybe deserialization of that strange object is not completed, but I have read that reading objects from ObjectInputStream is blocking, so all objects in my list must be in correct state. Or I something overlooked?
  • Are there any technique/tool/practice for catching things like this?

Thank you.

A: 

As I wrote in comment the problem was in touching items in serialized collection during Container.readObject(). Some of these objects had in this moment null fields. When I postponed their touching outside deserialization of Container, these objects had correct field values.

My hypothesis:

Lets have object parent with field collection of other objects children. Both parent and children are serializable, as well as collection. During customized parent deserialization in readObject() method aren't children fully accessible, they exists but its deserialization is not complete. You have to access children only after parent deserialization is processed.

This hypothesis works for me, but I still don't know why.

mschayna
Hypothesis still works for me, no more answers, accepting.
mschayna