[Forwarded email from "Joshua Bloch" <Joshua.Bloch@eng.sun.com>,
whose submissions keep bouncing because he is subscribed as
I did send a message on this topic about 10 days ago, but all I said was
(loosely speaking) "Isn't it a shame that serialization screws things up?"
Note that the problem occurs only in non-serializable classes with nontrivial
state and serializable subclasses. This isn't too common, but it does occur.
In particular, it's not uncommon for abstract classes with nontrivial state.
Generally speaking, it's an *extremely* bad idea to make an abstract class
implement Serializable, even if some implementers will want to make
serializable subclasses. This presents no problem if the abstract class has no
state that would have to get serialized (e.g., AbstractSet, AbstractList,
AbstractMap, wherein the child classes store all of the state), because such
classes naturally have no-args constructors. If, however, the class has state
associated with it, the framework designer is placed in the unpleasant position
that he must provide a no-args constructor and an init method, merely to allow
for serializable subclasses.
As a precaution, such classes should check to see that they're initialized
exactly once; subsequent attempts, and attempts to use the object before it's
initialized, should result in IllegalStateExceptions. All of that said, it's
*extremely* difficult to get the details right when you're trying to use such a
class. The problem is that object graphs getting deserialized can be in
transient states that they couldn't possibly be in when they were getting
constructed normally. The writer of the init method naturally assumes that any
object references passed into the init method represent fully constructed
objects (as they would in the normal, non-deserialization case) but this is not
the case when an object graph is getting deserialized. The program can easily
see object invariants fail, with non-deterministic results.
This situation is extremely confusing and hard to debug. It happens in
practice. It happened to me. The lesson that I took away from all of this was
that you simply shouldn't use this pattern unless you have no choice in the
matter, and are willing to field bug reports from confused developers. I ended
up taking out the no-args constructor and the init method, making the abstract
class ineligible for serializable subclasses.
From: Jerry Schwarz <firstname.lastname@example.org>
To: email@example.com <firstname.lastname@example.org>
Cc: Boehm, Hans <email@example.com>; JMM <javaMemoryModel@cs.umd.edu>
Date: Saturday, September 30, 2000 12:20 PM
Subject: Re: JavaMemoryModel: init methods
>One important place where this idiom is used that hasn't been mentioned is
>mention it because it has very different properties than the framework
examples. In particular it
>can be used on classes that do not have zero-arg constructors. This can be
done because the
>construction of the instance is performed in native code. I think it ought to
be the responsibility
>of ObjectInputStream to ensure that objects it returns can be used in threads,
but I've never seen
>any discussion of that question.
JavaMemoryModel mailing list - http://www.cs.umd.edu/~pugh/java/memoryModel
This archive was generated by hypermail 2b29 : Thu Oct 13 2005 - 07:00:27 EDT