Summary
For serializable method references, the deserialization code generated by javac does not consider the instantiated method type, which can lead to incompatible lambdas being merged together and result in ClassCastExceptions. This proposal changes the generated deserialization code to consider the instantiated method type.
Problem
Consider this code:
interface F<T, R> extends Serializable {
R apply(T t);
}
F<String, String> f = Object::toString;
F<Object, String> g = Object::toString;
When a lambda is deserialized, javac checks the functional interface class, method name, and signature; as well as the implementation class and method signature. All of those are the same for f and g, so serializing and deserializing g will cause it to be merged into the implementation of f. However the instantiated method type is different, f expects an instance of String, so invoking the deserialized lambda for g will fail with a ClassCastException.
Solution
The solution is to add a check on SerializedLambda#getInstantiatedMethodType in the deserialization logic.
That fix revealed another pre-existing issue, which is that the implementation class checked by the deserialization logic didn't match the runtime implementation class reported by SerializedLambda#getImplClass for interface methods that overrode java.lang.Object methods (see JDK-8374654 for more discussion). That bug was being masked in some cases because javac didn't consider getInstantiatedMethodType, so those methods could sometimes be successfully deserialized if they were merged into another serializable lambda in the same compilation unit. To avoid regressing that behaviour, this fix also updates how javac determines the implementation method for java.lang.Object methods in interfaces, to always resolve java.lang.Object as the implementation class in those cases.
Alternatives:
-
JDK-8068253 (MethodHandleInfo does not provide the referenced class) would simplify the handling of
java.lang.Objectmethods in interfaces, and provide an alternative solution JDK-8374654. It is also a larger change (it would affect the runtime SerializedLambda API) with more compatibility impact. -
Desugaring method references to interfaces has been discussed previously including in JDK-8154236. It would be a larger change with more compatibility impact, and affect the deserialization of existings lambdas.
Specification
No specification changes.
- csr of
-
JDK-8208752 Calling a deserialized Lambda might fail with ClassCastException
-
- Open
-