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

Expand serial warning to check for bad overloads of serial-related methods and ineffectual fields

XMLWordPrintable

    • Icon: CSR CSR
    • Resolution: Approved
    • Icon: P3 P3
    • 18
    • tools
    • None
    • behavioral
    • low
    • Hide
      Augmented checks could cause types which currently compile cleanly under `javac'`s `-Xlint:serial` to generate warnings.

      New warnings can be suppressed using `@SuppressWarnings("serial")` annotations and/or disabling the lint category.
      Show
      Augmented checks could cause types which currently compile cleanly under `javac'`s `-Xlint:serial` to generate warnings. New warnings can be suppressed using `@SuppressWarnings("serial")` annotations and/or disabling the lint category.
    • add/remove/modify command line option
    • JDK

      Summary

      Expand javac's Xlint:serial checking from checking the declaration of serialVersionUID fields to checking the declarations of all serialization-related fields and methods.

      Problem

      Mis-declaring serialization-related fields and methods can lead to runtime exceptions and silent failures.

      Solution

      Add checks for all the serialization and externalization related fields and methods:

      Serialization-related methods:

       private void writeObject(java.io.ObjectOutputStream stream) throws IOException;
       private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException;
       private void readObjectNoData() throws ObjectStreamException;
      ANY-ACCESS-MODIFIER Object writeReplace() throws ObjectStreamException;
      ANY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamException; 

      Serialization-related fields:

      private static final long serialVersionUID
      private static final ObjectStreamField[] serialPersistentFields

      The checks are triggered when a field or method in a serializable type has a name matching one of the serialization-related fields or methods, respectively.

      Additional checks are done for Externalizable types as some serialization-related methods are ineffectual there.

      The semantics of serialization are covered in the "Java Object Serialization Specification" (https://docs.oracle.com/en/java/javase/17/docs/specs/serialization/index.html), abbreviated as JOSS in the remainder of this CSR, as well as in portions of the core library specification, including the classes java.io.ObjectOutputStream and java.io.ObjectInputStream.

      The overall objective is to warn for cases where declarations cause the runtime serialization mechanism to silently ignore a mis-declared entity, rendering it ineffectual. Also, the checks include several compile-time patterns that could lead to runtime failures.

      The checks are specialized for each of serializable classes, interfaces, enum classes, and record classes. (Per the JLS annotation interfaces are not serializable.)

      For fields and methods in Serializable classes (not enums or records), the checks make sure:

      • mandatory modifiers are present (e.g. private on readObject and writeObject)
      • modifiers that should not be present are absent (e.g. static on readObject and writeObject; those methods must be instance methods)
      • for fields, the field is declared with the proper type
      • for methods, the return type, number and of type of parameters match and the throws clause is compatible (methods are not declared to throw any checked exceptions that are not subtypes of those thrown by the canonical method's signature)

      Existing checks that the serialVersionUID field is declared static final and of the right type, etc. are preserved.

      If serialPersistentFields is initialized to a literal null, a distinct warning is issued since a null serialPersistentFields field is ignored, JOSS 1.5.

      A serializable class is checked that it has access to a no-arg constructor in the first non-serializable class up its superclass chain (required in JOSS section 1.10). Note that java.lang.Object is not serializable and has a public non-arg constructor so the chain will terminate. An externalizable class is checked to have a public no-arg constructor (JOSS section 1.11).

      Warnings are issued if an externalizable class has a serialPersistentFields field, writeObject method, readObject method, or readObjectNoData method; those declarations are ineffectual for an externalizable class (JOSS 1.11 "An Externalizable class can optionally define the following methods: ... A writeReplace method to allow a class to nominate a replacement object to be written to the stream ... A readResolve method to allow a class to designate a replacement object for the object just read from the stream").

      For enum classes, since the serialization spec states the five serialization-related methods and two fields are all ignored (JOSS 1.12), the presence of any of those in an enum class will generate a warning.

      For record classes, from JOSS 1.13 "any class-specific writeObject, readObject, readObjectNoData, writeExternal, and readExternal methods defined by record classes are ignored during serialization and deserialization." Therefore, warnings are generated for the ineffectual declarations that serialization would ignore.

      For interfaces, if a public readObject, readObjectNoData, or writeObject method is defined, a warning is issued since a class implementing the interface will be unable to declare private versions of those methods and the methods must be private to be effective. If an interface defines default writeReplace or readResolve methods, a warning will be issued since serialization only looks up the super*class* chain for those methods and not for default methods from interfaces. Since a serialPersistentFields field must be private to be effective, the presence of such a (non-private) field an in interface generates a warning. The presence of a serialVersionUID field does not generate a warning, but the declaration is checked to conform to the field's requirements to be effective, having the proper type, etc. There are limited circumstances where the serialVersionUID of an interface are used.

      Specification

      The behavior in the Solution section above is intended to be a full and accurate description of the expansion in -Xlint:serial checking. There is not a specification document per se for the lint behavior, other than summary statements in the javac help messages and similar usage documentation.

      The description of -Xlint:serial is updated as follows:

      -    Warn about Serializable classes that do not provide a serial version ID. \n\
      -\                         Also warn about access to non-public members from a serializable element.
      +    Warn about Serializable classes that do not have a serialVersionUID field. \n\
      +\                         Also warn about other suspect declarations in Serializable and Externalizable classes and interfaces.

            darcy Joe Darcy
            darcy Joe Darcy
            Roger Riggs, Stuart Marks
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved: