Unable to deserialize lambda

You can’t deserialize an object without the class defining it. This hasn’t changed with lambda expressions.

Lambda expressions are a bit more complex as their generated runtime class is not the class which defined it but their defining class is the one holding the code of the lambda’s body and, in case of serializable lambdas, a deserialization support method which is called for validating and re- instantiating the lambda instance.

See SerializedLambda:

Implementors of serializable lambdas, such as compilers or language runtime libraries, are expected to ensure that instances deserialize properly. One means to do so is to ensure that the writeReplace method returns an instance of SerializedLambda, rather than allowing default serialization to proceed.

SerializedLambda has a readResolve method that looks for a (possibly private) static method called $deserializeLambda$(SerializedLambda) in the capturing class, invokes that with itself as the first argument, and returns the result. Lambda classes implementing $deserializeLambda$ are responsible for validating that the properties of the SerializedLambda are consistent with a lambda actually captured by that class.

So even if your instance was not referring to a synthetic method inside the defining class (e.g. in the case of a method reference to a method outside this class), deserialization still requires the $deserializeLambda$ for validating the correctness of the instance, intentionally.


Regarding the “good practice” of serializing lambdas, keep in mind that lambda expressions encapsulate behavior, not state. Storing behavior always implies storing just some kind of reference and requiring the code intended to restore it, to have implemented the associated behavior. That would work as well if you just referred to the intended behavior by a symbolic name or just stored, e.g. associated enum values.

More about the implications of having serializable lambdas is explained in this question.

Leave a Comment