Deserialization of a linked list of records
    Chris Hegarty 
    chris.hegarty at oracle.com
       
    Sun Feb 28 16:11:29 UTC 2021
    
    
  
Remi,
On 26 Feb 2021, at 22:06, Remi Forax <forax at univ-mlv.fr<mailto:forax at univ-mlv.fr>> wrote:
[sent to both email list given it's not clear if it's an implementation issue or a spec issue]
There is a nice video of how the serialization of records works recently on inside.java
https://inside.java/2021/02/23/records-met-serialization/
Yes, this is a nice explanation of how record serialization works.
In the video, Julia explains that the de-serialization works from bottom-up, so what if the record instances are a linked list ...
answer: a stack overflow.
Here is a small reproducer.
This reproducer fails on my machine with a StackOveflowException when serializing ( not de-serializing ).
It fails with:
Exception in thread "main" java.lang.StackOverflowError
  at java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1142)
  at java.base/java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1577)
  at java.base/java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1534)
  at java.base/java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1443)
  at java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1186)
  at java.base/java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1577)
  at java.base/java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1534)
  at java.base/java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1443)
  at java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1186)
  at java.base/java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1577)
  at java.base/java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1534)
  at java.base/java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1443)
  at java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1186)
  at java.base/java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1577)
  ...
The same is true if Link is a normal class ( not a record class ).
Records and normal classes share the same code path in OOS when serializing.
-Chris.
import static java.util.stream.IntStream.range;
public class RecordSerializationFailure {
 record Link(Object value, Link next) implements Serializable {}
 public static void main(String[] args) throws IOException, ClassNotFoundException {
   var link = range(0, 1_000_000)
       .boxed()
       .<Link>reduce(null, (next, i) -> new Link(i, next), (_1, _2) -> null);
   var path = Path.of("serial.data");
   try(var output = Files.newOutputStream(path);
       var oos = new ObjectOutputStream(output)) {
     oos.writeObject(link);
   }
   Link result;
   try(var input = Files.newInputStream(path);
       var ois = new ObjectInputStream(input)) {
     result = (Link) ois.readObject();
   }
   System.out.println(link.equals(result));
 }
}
Should this be fixed or not ?
regards,
Rémi
    
    
More information about the amber-dev
mailing list