JEP 187: Serialization 2.0 & Serialization-aware constructors
snazy at gmx.de
Wed Jan 22 21:34:13 UTC 2014
Am 22.01.2014 um 17:33 schrieb "David M. Lloyd" <david.lloyd at redhat.com>:
> The concept of explicit deserialization constructors is interesting and is something I've explored a little bit in the context of JBoss Marshalling.
> The idea with a serialization-aware constructor is that each serializable class constructor can read the stream information itself and initialize fields the "normal" way, with "normal" validation.
I agree with David.
One thing to think about might be to introduce a special kind of constructor by extending the JLS - to introduce a special "deserialization constructor" that behaves a bit different than "normal" constructors.
Deserialization-constructors are called "top-down" (java.lang.Object first) - the deserialization code is responsible to call the deserialization-constructors for each individual class.
The deserialization-constructor receives information only for deserialized fields that the class "owns" (not for fields of any superclass or subclass).
But: deserialization-constructors should not be callable from "normal" code.
Maybe there could be multiple "deserialization constructors" - one per serialVersionUID. This should completely eliminate "spaghetti code" in "readObject()" and the need for "readObject()" at all.
Another idea is to introduce a kind of "protocol" how to deal with incompatible class changes or serial-version-uid mismatches. This gets important when existing applications grow: how shall a new field be initialized, when it's not present in input stream? Maybe this could be handled by the "deserialization constructor".
Regarding the situation when an older implementation reads data from a newer implementation (with more fields or changed fields) ... I think that special situation cannot be handled. But it might be possible to serialize objects explicitly for older versions - for example if the implementation knows that it creating an RPC response for an older client. writeObject() could be replaced with "serialization methods" - multiple "serialization methods" could be used to address different versions.
A new serialization framework should also add support for classes with "factory methods" like those with static "valueOf(...)" methods - maybe in combination to replace readResolve/writeReplace.
Serialization should also respect immutable objects like String, Byte/Integer/Long/..., InetAddress, UUID - this reduces the serialized payload and amount of (unnecessary) objects during deserialization.
Maybe serialization should move a bit deeper into the JVM itself - to optimize the reflection/unsafe stuff.
IMHO the explicit serialFields support should not be supported for "serialization 2.0" - maybe I'm wrong, but I do not know any code that uses this (except some core JDK classes) - for me it looks like a workaround to deal with incompatible class changes.
Transport and serialization might be separated in "serialization 2.0". Current OOS/OIS implementations perform a lot of System.arraycopy operations and allocate a lot of temporary objects (e.g. during string (de)serialization). It should be possible to "feed" deserialization with ByteBuffers - for example by using NIO. For example: the current internal "readPrimitives()" method could directly operate on a ByteBuffer without any copy operation - maybe with native support from the JVM.
More information about the core-libs-dev