JDK-8174864 : SerializedLambda does not preserve markers & bridges
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.lang.invoke
  • Affected Version: 8u101,9
  • Priority: P4
  • Status: In Progress
  • Resolution: Unresolved
  • Submitted: 2017-02-13
  • Updated: 2022-03-08
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
tbd_majorUnresolved
Related Reports
Relates :  
Relates :  
Relates :  
Relates :  
Description
SerializedLambda has fields storing most of the arguments to LambdaMetafactory (sometimes after mapping to a serialization-friendly form). But it does not have fields to store extra interfaces or extra method descriptors, as supported by 'altMetafactory'. As a result, serialization must be a lossy transformation, mapping many function objects to the same serialized form.

Thus, while LambdaMetafactory promises to support serialization of any legal invocation that uses FLAG_SERIALIZABLE, in practice only the first invocation of a unique serialization key (key=the first 6 arguments) will serialize/deserialize correctly.
Comments
Here's an example that shows (I think) that the type parameters aren't captured either. This seems related to but slightly different from the example in JDK-8174865. @SuppressWarnings("unchecked") static <T> T serClone(T f) throws Exception { var baos = new ByteArrayOutputStream(); try (var oos = new ObjectOutputStream(baos)) { oos.writeObject(f); } try (var bais = new ByteArrayInputStream(baos.toByteArray()); var ois = new ObjectInputStream(bais)) { return (T)ois.readObject(); } } public static void main(String[] args) throws Exception { Function<BigInteger, String> f1 = (Function<BigInteger, String> & Serializable) Object::toString; Function<UUID, String> f2 = (Function<UUID, String> & Serializable) Object::toString; Function<BigInteger, String> s1 = serClone(f1); Function<UUID, String> s2 = serClone(f2); s1.apply(BigInteger.ZERO); s2.apply(UUID.randomUUID()); // CCE thrown here } Derived from this reddit thread: https://www.reddit.com/r/java/comments/8i9nd6/a_surprising_feature_of_method_references/
01-06-2018

Also missing: types of captured parameters. While the captured arguments themselves *are* serialized, different LambdaMetafactory invocations might view them as having different types. This can only be observed if the capture types are different than the implMethod types (see JDK-8174983). See discussion of JDK-8154236.
17-03-2017

See JDK-8174865 for an illustration of how this problem manifests in javac-generated code.
13-02-2017