Description
The current implementations of writeExternal
and readExternal
are inconsistent in the way they serialize and deserialize data. On the one hand, writeExternal
first serializes each data field into its individual byte array that is then written to writeExternal
's ObjectOutput
. On the other hand, readExternal
deserializes the data as if it all has been written directly to the ObjectOutput
without any intermediate FieldOut
-> DataOutputStream
-> ByteArrayOutputStream
-> byte[]
steps.
Such approach may works in some cases (for example, when using standard Java serialization) and some others, unfortunately, it does not (for example, https://issues.apache.org/jira/browse/IGNITE-1001).
Specifically, the current implementation incorrectly assumes that on-the-wire representation produced by the DataOutputStream
is the same as the one that would have been produced by the ObjectOutput
had it been used directly, and is indeed the one that ObjectInput
(passed into readExternal
) knows how to read. However, different serialization libraries may use different approaches to serializing data. For example, DataOutput.writeUTF()
implementations vary widely in how they serialize the length of the string, as well as its characters. So the current approach of writing a UTF string using DataOutputStream
's implementation and then reading it using some other serializer's DataInput
implementation is never guaranteed to work reliably.
The good news is that the fix is really simple: read the entire byte array in readExternal
method and wrap it into a DataInputStream
instance, which is then used to deserialize the rest of Config
's hierarchy.
I have a fix. It's literally 4 lines of code.