Serialized lambda and no serialVersionUID?

I am trying to find out how serialization works with Java and its latest version. I am trying to serialize lambda as follows:

Runnable r = (Runnable & Serializable)() -> {System.out.println("This is a test");}; 

But I notice that I have no warning about the absence of the variable serialVersionUID . This is normal?

I know that it will be created at runtime, however it is highly recommended to define it: https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html

If the serializable class does not explicitly declare a serialVersionUID, then the serialization runtime will calculate the default serialVersionUID for this class based on various aspects of the class, as described in the serialization of the Java (TM) specification. However, it is strongly recommended that all serializable classes explicitly declare serialVersionUID values, since the default calculation of serialVersionUID is very sensitive to the part class, which may vary depending on compiler implementations and may thus lead to unexpected InvalidClassExceptions during deserialization. Therefore, in order to guarantee a consistent serialVersionUID value in different java compiler implementations, the serializable class must declare an explicit serialVersionUID value. It is also strongly recommended that explicit declarations of serialVersionUID be used whenever possible, since such declarations apply only to immediately declaring classes - serialVersionUID fields are not useful as inherited. Array classes cannot declare explicit serialVersionUIDs, so they always have a default value, but the serialVersionUID values ​​match the requirements for array classes.

What should I do? How can I define it in my lambda?

thanks

+6
java lambda java-8 serialization serialversionuid
source share
1 answer

serialVersionUID applies only to classes that generate a stream identifier . This is not the case if the serializable class has a writeReplace() method (also described in the Serializable documentation ) that returns a replacement object of another class, since such a representation is completely separate from the original class. This is what happens with serializable instances of lambda, see SerializedLambda :

It is assumed that developers of serializable lambdas, such as compilers or runtime libraries, ensure that instances are deserialized properly. One of them is to ensure that the writeReplace method returns an instance of SerializedLambda , rather than allowing default serialization.

So, its instance is SerializedLambda , which gets into the stream, and therefore the responsibility of this class is to have a stable serialized representation. Unfortunately, this does not protect you from possible incompatibilities.

After deserialization, a synthetic class method will be called that defines the lambda expression (compare this answer as well ), which will reject deserialization attempts that do not match the existing definition of the lambda expression inside this class, while the match may depend on the subtle aspects of the definition of lambda. Note that even recompiling the defining class with Eclipse rather than javac can break Serialization compatibility.

Not affected by the security impact of Serializable lambdas . As a rule, I recommend not using it.

+6
source share

All Articles