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

Vector should throw ClassNotFoundException for a missing class of an element



    • behavioral
    • minimal
    • The behavior that is changed only occurs in environments that are not configured to be able to load expected classes and changes unexpected behavior to the expected behavior.
    • Java API
    • Implementation



      java.util.Vector should throw ClassNotFoundException instead of StreamCorruptedException; the wrong exception is thrown due to incorrect handling of a missing class by ObjectInputStream.GetField.get(name, object).


      During deserialization, java.util.Vector uses ObjectInputStream.readFields() to retrieve the serialized array elements in elementData.

      The problem with OIS.GetField(name, object) has only been reported as a problem affecting Vector though it may be affecting other implementations using OIS.readFields(). The implementation of OIS.GetField.get(name, object) returns null when it should throw CNFE. See JDK-8273660.

      Vector checks the elementData and throws StreamCorruptedException if it is null. The null can be due to more than one condition, including the field is null, the field is not present in the stream, and the field is null because one of the array elements could not be deserialized due to a missing class. The first two cases reflect a corrupted stream but the third should result in a ClassNotFoundException being thrown from OIS.readObject().

      During deserialization the graph encoded in the stream is reconstructed. If the class of an object is not found, the CNFE is recorded but is not thrown, and deserialization continues. Other instances that depend upon this object are also marked with the exception, all the way up to the root of the object graph. If the root object is marked with a CNFE, the top level OIS.readObject() call will throw CNFE. Thus, CNFE will be thrown from the top level call if the root object depends transitively on any object for which CNFE was encountered.

      If an object's readObject method throws CNFE, it is handled by deserialization via the dependency mechanism described above. Note that another thrown CNFE does not replace a previously recorded CNFE. However, any other exception type will terminate deserialization and will propagate to the caller. This causes any recorded CNFE to be discarded. The issue in the case of Vector is that it converts the null for elementData into a StreamCorruptedException which preempts the normal tracking of the CNFE to the root of the object graph. The discarding of the CNFE makes it difficult to diagnose the root cause of the deserialization failure.


      In the case of null elementData the original ClassNotFoundException should be preserved. Since CNFE is handled by deserialization, Vector can throw CNFE instead of StreamCorruptedException in the cases where the latter might discard the original CNFE. The CNFE that is thrown should identify the cause as a null elementData in the case where it was caused by a missing class or if the field is present and null. For the case where the elementData field is missing from the stream, StreamCorruptedException should still be thrown.


      The behavior of Vector is modified so that if the class of an Element is not found, a ClassNotFoundException is thrown from the top level OIS.readObject reflecting the missing class. If the elementData array in the stream is null, a ClassNotFoundException will be thrown with a message indicating that elementData is null. There are no normal uses of Vector in which this will occur.

      There is no specification change for Vector. Instead of the previous behavior in which a StreamCorruptedException is erroneously thrown for a missing class, ClassNotFoundException will be thrown.


        Issue Links



              rriggs Roger Riggs
              rriggs Roger Riggs
              Stuart Marks
              0 Vote for this issue
              1 Start watching this issue