CONTENTS | PREV | NEXT
A.5 Writing Class-Specific Serializing Methods
To guarantee that a deserialized object does not have state which violates some set of invariants that need to be guaranteed, a class can define its own serializing and deserializing methods. If there is some set of invariants that need to be maintained between the data members of a class, only the class can know about these invariants, and it is up to the class author to provide a deserialization method that checks these invariants.Security-conscious implementors should keep in mind that a serializable class' readObject method is effectively a public constructor, and should be treated as such. This is true whether the readObject method is implicit or explicit. It is not safe to assume that the byte stream that is provided to the readObject method was generated by serializing a properly constructed object of the correct type. It is good defensive programming to assume that the byte stream is provided by an adversary whose goal is to compromise the object under construction.
This is important even if you are not worried about security; it is possible that disk files can be corrupted and serialized data be invalid. So checking such invariants is more than just a security measure; it is a validity measure. However, the only place it can be done is in the code for the particular class, since there is no way the serialization package can determine what invariants should be maintained or checked.
In version 1.4 of the Java 2 SDK, Standard Edition, support was added for class-defined readObjectNoData methods (see Section 3.5, "The readObjectNoData Method"). Non-final serializable classes which initialize fields to non-default values should define a readObjectNoData method to ensure consistent state in the event that a subclass instance is deserialized and the serialization stream does not list the class in question as a superclass of the deserialized object. This may occur in cases where the receiving party uses a different version of the deserialized instance's class than the sending party, and the receiver's version extends classes that are not extended by the sender's version. This may also occur if the serialization stream has been tampered; hence, readObjectNoData is useful for initializing deserialized objects properly despite a "hostile" or incomplete source stream
CONTENTS | PREV | NEXT