Stability of lambda serialization
Scott Stark
sstark at redhat.com
Tue Jul 23 10:35:26 PDT 2013
Red Hat has a concern regarding how fragile the default serialization behavior of lambda expressions is in the current reference implementation, currently:
ironmaiden:OpenJDK starksm$ /Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Home/bin/java -version
java version "1.8.0-ea"
Java(TM) SE Runtime Environment (build 1.8.0-ea-b98)
Java HotSpot(TM) 64-Bit Server VM (build 25.0-b40, mixed mode)
The problem is that the serialized form of a lambda expression depends on the order in which captured arguments are declared. The attached simple example demonstrates how easy it is for a trivial reordering of the lambda code block to result in an inability to deserialize a previously saved expression.
To produce this exception:
1. Run the serialization.AuthenticationContext.testWriteLambda method with the lambda expression written as:
Authenticator a = (Authenticator & Serializable) (String principal, char[] pass) -> {
// Run with p declared first when writing out the /tmp/testWriteLambda.bin, then switch
// to declare u first when running testReadLambda
String p = "-> Password " + password + " <-";
String u = "-> User " + user + " <-";
return u + " " + p;
};
2. Change the lambda expression to:
Authenticator a = (Authenticator & Serializable) (String principal, char[] pass) -> {
// Run with p declared first when writing out the /tmp/testWriteLambda.bin, then switch
// to declare u first when running testReadLambda
String u = "-> User " + user + " <-";
String p = "-> Password " + password + " <-";
return u + " " + p;
};
Recompile and run serialization.AuthenticationContext.testReadLambda to produce:
java.io.IOException: unexpected exception type
at java.io.ObjectStreamClass.throwMiscException(ObjectStreamClass.java:1538)
at java.io.ObjectStreamClass.invokeReadResolve(ObjectStreamClass.java:1110)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1807)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1348)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370)
at serialization.AuthenticationContext.testReadLambda(AuthenticationContext.java:34)
...
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.invoke.SerializedLambda.readResolve(SerializedLambda.java:222)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.io.ObjectStreamClass.invokeReadResolve(ObjectStreamClass.java:1104)
... 30 more
Caused by: java.lang.IllegalArgumentException: Invalid lambda deserialization
at serialization.AuthenticationContext.$deserializeLambda$(AuthenticationContext.java:1)
... 40 more
One does not see the same level of sensitivity to the ordering of the serialization fields in a POJO as demonstrated by the serialization.AuthenticationContext.testWritePOJO/testReadPOJO cases where one can reorder the TestPOJO.{user,password} fields without having serialization fail.
We would like to see at least that level of stability of the serialized form of lambda expressions.
More information about the lambda-spec-observers
mailing list