Stability of lambda serialization

Paul Benedict pbenedict at apache.org
Sat Aug 3 16:54:58 PDT 2013


I imagine this will mostly impact EE applications in a very negative way.
It's one thing if my method signatures change, or I explicitly add some
fields, but now adding/removing a local lambda will do that? Serialization
errors are the worst thing in EE -- and this kind of just heaps on more
misery.

Paul


On Sat, Aug 3, 2013 at 2:00 AM, Brian Goetz <brian.goetz at oracle.com> wrote:

> This was discussed in the meeting after JVMLS this week.  The consensus
> was that, while *this particular* issue could be addressed, there is an
> infinite spectrum of similar issues that cannot be addressed, and that it
> is preferable to draw a clean line about what the user can expect in terms
> of code changes destabilizing lambdas.
>
> That line is: If the code inside a method, or the method's signature,
> changes *in any way*, lambdas captured in that method should be considered
> destabilized.  Changes to other methods, or changes to the order of
> methods, do not affect lambdas in an unchanged method.
>
> On Jul 23, 2013, at 10:35 AM, Scott Stark wrote:
>
> > 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.
> > <AuthenticationContext.java><TestPOJO.java><Authenticator.java>
>
>


-- 
Cheers,
Paul


More information about the lambda-spec-observers mailing list