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

ObjectInputStream.GetField.get returns null instead of handling ClassNotFoundException

XMLWordPrintable

    • Icon: CSR CSR
    • Resolution: Withdrawn
    • Icon: P3 P3
    • None
    • core-libs
    • None
    • behavioral
    • low
    • Hide
      The behavioral compatibility risk is low since the special case of the `IOException` thrown at a very low level is handled by the implementation as if `ClassNotFoundException` was thrown.

      A system property `jdk.serialGetFieldCnfeReturnsNull` is added to allow an application to revert to the old behavior.
      Show
      The behavioral compatibility risk is low since the special case of the `IOException` thrown at a very low level is handled by the implementation as if `ClassNotFoundException` was thrown. A system property `jdk.serialGetFieldCnfeReturnsNull` is added to allow an application to revert to the old behavior.
    • Java API
    • Implementation

      Summary

      The ObjectInputStream.FieldValues.get(String name, Object val) method is returning null instead of throwing an exception when the class of the object is not found. The caller is not able to correctly handle the case where the class is not found. An exception should be thrown.

      The problem is the same for all versions of the JDK. The solution in JDK-8276742 for the mainline is to update the signature of GetField.get and throw ClassNotFoundException.

      Problem

      When using ObjectInputStream.readFields, it may be the case that while deserializing an object, a class being deserialized is not found. There is currently a bug such that though the ClassNotFoundException is recorded, it is not reported and null is returned instead. The specification is silent on this particular case, and returning null (except when the field value is actually null) is not supported by the specification. The caller is likely to misinterpret the null as a field value.

      ObjectInputStream.readFields() is used to provide access to field values read from the stream. The returned ObjectInputStream.GetField instance holds the values read for later retrieval. For a missing class, the ClassNotFoundException is correctly recorded for its field. However, calling ObjectInputStream.FieldValues.get(String name, Object val) method is unable to throw the CNFE because the method signature does not include the needed throws clause.

      This bug has been present since JDK 1.4 and has caused an issue with customers in JDK 7 and more recent versions.

      This change only applies to uses of ObjectInputStream.readFields and does not apply to cases where defaultReadObject is used by a class implementing its own readObject method.

      Solution

      An IOException should be thrown from GetField.get to prevent the caller from continuing to process the field value as if it were valid. The ClassNotFoundException recorded for the field is wrapped in an IOException and thrown allowing the caller to correctly identify the cause. Note that GetField.get is only callable from the readObject method of the class being deserialized; it is rare that any caller actually catches either ClassNotFoundException or IOException; both are typically handled further up the call stack.

      The ObjectInputStream.readFields and GetField.get method can only be called from inside the readObject method by the implementation of ObjectInputStream.readObject. The ObjectInputStream implementation handles the specific case of IOException wrapping a ClassNotFoundException correctly to identify the missing class and throw the ClassNotFoundException.

      A system property jdk.serialGetFieldCnfeReturnsNull is added to allow an application to revert to the old behavior.

      Specification

      There is no change to the specification for previous JDK versions but the behavior may observed by a caller catching IOException. Both IOException and ClassNotFoundException typically terminate deserialization.

            rriggs Roger Riggs
            shadowbug Shadow Bug
            Stuart Marks
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: