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

Different method references deserialize to the same class

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Unresolved
    • Icon: P4 P4
    • tbd
    • 8u101, 9
    • tools

      The SerializedLambda class doesn't encode the extra interfaces and method descriptors provided to 'altMetafactory'. As a result, method references that refer to the same method but with different target types can end up being deserialized to the same class, leaving one of the deserialized objects with either too many or too few interfaces/bridges.

      --------

      Test:

      import java.util.Arrays;
      import java.io.*;

      public class LambdaSerialization {

          interface I {}

          public static void main(String... args) throws Exception {
              Runnable r1 = (Runnable & Serializable) System::gc;
              Runnable r2 = (Runnable & Serializable & I) System::gc;
              test(r1);
              System.out.println();
              test(r2);
          }
          
          public static void test(Object o1) throws Exception {
              System.out.printf("Starting object %s implements %s%n", o1, Arrays.asList(o1.getClass().getInterfaces()));
              try (ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
                      ObjectOutputStream out = new ObjectOutputStream(outBytes)) {
                  out.writeObject(o1);
                  out.flush();
                  try (ByteArrayInputStream inBytes = new ByteArrayInputStream(outBytes.toByteArray());
                          ObjectInputStream in = new ObjectInputStream(inBytes)) {
                      Object o2 = in.readObject();
                      System.out.printf("Deserialized object %s implements %s%n", o2, Arrays.asList(o2.getClass().getInterfaces()));
                  }
              }
          }

      }

      This program prints:

      Starting object LambdaSerialization$$Lambda$1/989110044@404b9385 implements [interface java.lang.Runnable, interface java.io.Serializable]
      Deserialized object LambdaSerialization$$Lambda$4/284720968@b4c966a implements [interface java.lang.Runnable, interface java.io.Serializable]

      Starting object LambdaSerialization$$Lambda$2/1096979270@2f4d3709 implements [interface java.lang.Runnable, interface LambdaSerialization$I, interface java.io.Serializable]
      Deserialized object LambdaSerialization$$Lambda$4/284720968@b4c966a implements [interface java.lang.Runnable, interface java.io.Serializable]

      --------

      The API deficiency is reported in JDK-8174864. Possible ways forward:
      - Wait for JDK-8174864 to be addressed, then adapt $deserializeLambda$ code-gen logic
      - Detect when a serialized form clash will occur (different LambdaMetafactory parameters, same SerializedLambda), and generate a lambda bridge for the second occurrence
      - *Always* generate a lambda bridge when, say, FLAG_BRIDGES or FLAG_MARKERS would be needed.

            dlsmith Dan Smith
            dlsmith Dan Smith
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated: