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

Deserialization fails with cyclic object graph and serial proxy

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Unresolved
    • Icon: P4 P4
    • tbd
    • 1.4.2, 8
    • core-libs

      FULL PRODUCT VERSION :
      1.8.0-ea-b106

      A DESCRIPTION OF THE PROBLEM :
      A lambda that captures a value that refers back to that lambda cannot be properly deserialized. This is caused by the usage of readResolve() in java.lang.invoke.SerializedLambda.


      ACTUAL -
      The cyclic reference is not resolved, an instance of java.lang.invoke.SerializedLambda is used where a lambda is expected.

      ERROR MESSAGES/STACK TRACES THAT OCCUR :
      first example:
      java.lang.ClassCastException: cannot assign instance of java.lang.invoke.SerializedLambda to field SerialLambda.supplier of type SerialLambda$SerializableIntSupplier in instance of SerialLambda
      at java.io.ObjectStreamClass$FieldReflector.setObjFieldValues(ObjectStreamClass.java:2089)
      ...
      at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371)
      at SerialLambda.serialCopy(SerialLambda.java:32)
      at SerialLambda.go(SerialLambda.java:19)

      second example:
      Exception in thread "main" java.lang.ClassCastException: java.lang.invoke.SerializedLambda cannot be cast to SerialLambda$SerializableIntSupplier
      at SerialLambda.lambda$go2$9b75$0(SerialLambda.java:24)
      at SerialLambda$$Lambda$2.getAsInt(Unknown Source)
      at SerialLambda.go2(SerialLambda.java:26)

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      import java.io.*;
      import java.util.*;
      import java.util.function.IntSupplier;

      /** @author Wouter Coekaerts */
      public class SerialLambda implements Serializable {
        interface SerializableIntSupplier extends IntSupplier, Serializable {}

        public static void main(String[] args) throws Exception {
          new SerialLambda().go();
          go2();
        }

        SerializableIntSupplier supplier;

        void go() throws Exception {
          supplier = this::hashCode;
          System.out.println(serialCopy(this).supplier.getAsInt());
          System.out.println(serialCopy(this.supplier).getAsInt());
        }

        static void go2() throws Exception {
          List<SerializableIntSupplier> list = new ArrayList<>();
          list.add(() -> list.get(0).hashCode());
          System.out.println(serialCopy(list).get(0).getAsInt());
          System.out.println(serialCopy(list.get(0)).getAsInt());
        }

        @SuppressWarnings("unchecked")
        static <T> T serialCopy(T o) throws Exception {
          ByteArrayOutputStream ba = new ByteArrayOutputStream();
          new ObjectOutputStream(ba).writeObject(o);
          return (T) new ObjectInputStream(new ByteArrayInputStream(ba.toByteArray())).readObject();
        }
      }
      ---------- END SOURCE ----------

            smarks Stuart Marks
            alanb Alan Bateman
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated: