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

ClassCastException in ObjectInputStream hides ClassNotFoundException

XMLWordPrintable

      A DESCRIPTION OF THE PROBLEM :
      I'd like to provide a reproducible for JDK-8304814. Under the hood java.lang.ClassCastException: Cannot cast java.util.CollSer hides ClassNotFoundException.  It can be easily reproduced with both Class or Record that reference an immutable map that contains objects of missing classes. 

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      1. Serialise data to file : java TestClassCastException write
      2. rm DeletedClass.class
      3. Read file java TestClassCastException read

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      java.lang.ClassNotFoundException
      ACTUAL -
      For classes it throws Exception in thread "main" java.lang.ClassCastException: cannot assign instance of java.util.CollSer to field TestClassCastException$C.data of type java.util.Map in instance of TestClassCastException$C at java.base/java.io.ObjectStreamClass$FieldReflector.setObjFieldValues(ObjectStreamClass.java:2096) at java.base/java.io.ObjectStreamClass$FieldReflector.checkObjectFieldValueTypes(ObjectStreamClass.java:2060) at java.base/java.io.ObjectStreamClass.checkObjFieldValueTypes(ObjectStreamClass.java:1347) at java.base/java.io.ObjectInputStream$FieldValues.defaultCheckFieldValues(ObjectInputStream.java:2679) at java.base/java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2486) at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2257) at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1733) at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:509) at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:467) at TestClassCastException.read(TestClassCastException.java:40) at TestClassCastException.main(TestClassCastException.java:24)

      For records it throwsException in thread "main" java.io.InvalidObjectException: Cannot cast java.util.CollSer to java.util.Map at java.base/java.io.ObjectInputStream.readRecord(ObjectInputStream.java:2363) at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2251) at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1733) at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:509) at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:467) at TestClassCastException.read(TestClassCastException.java:41) at TestClassCastException.main(TestClassCastException.java:22)Caused by: java.lang.ClassCastException: Cannot cast java.util.CollSer to java.util.Map at java.base/java.lang.Class.cast(Class.java:3889) at java.base/java.io.ObjectInputStream.readRecord(ObjectInputStream.java:2361) ... 6 more

      ---------- BEGIN SOURCE ----------
      import java.io.File;
      import java.io.FileInputStream;
      import java.io.FileOutputStream;
      import java.io.InputStream;
      import java.io.ObjectInputStream;
      import java.io.ObjectOutputStream;
      import java.io.OutputStream;
      import java.io.Serializable;
      import java.util.LinkedHashMap;
      import java.util.Map;


      public class TestClassCastException {
          public static void main(String[] args) throws Exception {
              File f = new File("/tmp/write.ser");
              if (args.length > 0 && args[0].equals("write")){
                  Map m = Map.of("key", new DeletedClass());
                  TestClassCastException.R r = new TestClassCastException.R(m);
                  f.delete();
                  write(new FileOutputStream(f), r);
              } else{
                  read(new FileInputStream(f));
              }

          }

          public record R(Map<String, Map> data) implements Serializable {

          }

          private static void read(InputStream str) throws Exception {
              try (ObjectInputStream ois = new ObjectInputStream(str)) {
                  Object o = ois.readObject();
                  System.out.println(o);
              }
          }

          private static void write(OutputStream os, Object o) throws Exception {
              try (ObjectOutputStream os2 = new ObjectOutputStream(os)) {
                  os2.writeObject(o);
              }
          }
      }


      import java.io.Serializable;

      public class DeletedClass implements Serializable {
      }

      ---------- END SOURCE ----------

      FREQUENCY : always


            rriggs Roger Riggs
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            6 Start watching this issue

              Created:
              Updated:
              Resolved: