-
CSR
-
Resolution: Withdrawn
-
P3
-
None
-
None
-
behavioral
-
low
-
-
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.
- csr of
-
JDK-8273660 ObjectInputStream.GetField.get returns null instead of handling ClassNotFoundException
-
- Closed
-
- relates to
-
JDK-8276742 ObjectInputStream.GetField.get(name, object) should throw ClassNotFoundException
-
- Closed
-