Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8286047

Lambda deserialization fails for Object method references on interfaces

    XMLWordPrintable

    Details

    • Type: CSR
    • Status: Closed
    • Priority: P2
    • Resolution: Approved
    • Fix Version/s: 19
    • Component/s: tools
    • Labels:
      None
    • Subcomponent:
    • Compatibility Kind:
      behavioral
    • Compatibility Risk:
      low
    • Interface Kind:
      Other
    • Scope:
      Implementation

      Description

      Summary

      For serializable method references that invoke methods from java.lang.Object on interfaces, javac may generate a code that will prevent deserialization of such references in JDK 18. The proposal here is to fix this specific problem, and allow the deserialization as it happened in JDK 17. It is not intended to fix any other problem related to serializable lambdas and/or method references.

      Problem

      Consider this code:

        interface I extends Serializable {}
      
        interface F<T, R> extends Serializable {
          R apply(T t);
        }
      
         F<I, Integer> f = I::hashCode;

      When "f" is serialized, it is recorded that the method handled that should be invoked is java.lang.Object::hashCode. This is a pre-existing behavior. javac used to generate desugaring code that handled this input correctly, but after JDK-8272564, javac now expected I::hashCode to be stored in the serialized stream, which then breaks deserialization of the serialized value.

      Solution

      javac will be fixed to expect java.lang.Object::hashCode as the serialized method handle. This should return serialization and deserialization behavior for the aforementioned case back to JDK 17 state. Existing serialized representations should work as they did in JDK 17, but classfiles produced by JDK 18 won't be able to deserialize them.

      The exact behavior is summarized in the following table. The JDKs considered are unmodified JDK 17, JDK 18; and a JDK 19 with the proposed patch. The behavior is determined by the version of the JDK that compiled the code snippet, not by the version of JDK that serialized the method reference. -source/-target/--release options are irrelevant.

      serialized method reference by code built by unmodified JDK 17serialized method reference by code built by unmodified JDK 18serialized method reference by code built by patched JDK 19
      deserialized method reference by code built by unmodified JDK 17successsuccesssuccess
      deserialized method reference by code built by unmodified JDK 18failurefailurefailure
      deserialized method reference by code built by patched JDK 19successsuccesssuccess

      The "success" means the given JDK can deserialize the serialized stream produced by the given source JDK, "failure" means the given JDK cannot deserialize the stream produced by the given source JDK.

      No other pre-existing problems with serialization/deserialization of lambdas and/or method references are intended to be fixed.

      Specification

      Deserialization code generated by javac will expect java.lang.Object as the receiver, not the interface, for cases where we refer to a java.lang.Object method via an interface that does not override it.

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              jlahoda Jan Lahoda
              Reporter:
              cushon Liam Miller-Cushon
              Reviewed By:
              Vicente Arturo Romero Zaldivar
              Votes:
              0 Vote for this issue
              Watchers:
              4 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved: