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

Add missing serialization functionality to sun.reflect.ReflectionFactory

XMLWordPrintable

    • Icon: CSR CSR
    • Resolution: Approved
    • Icon: P4 P4
    • 24
    • core-libs
    • None
    • behavioral
    • minimal
    • The methods are new, so there should be no risk of compatibility changes with their introduction.
    • Java API
    • JDK

      Summary

      Add methods to allow serialization frameworks to serialize and deserialize objects which implement Serializable safely using standard reflection instead of Unsafe.

      Problem

      Issue JDK-8164908 added support for functionality required to continue to support IIOP and custom serializers in light of additional module-based restrictions on reflection. It was expected at the time that these libraries would use sun.misc.Unsafe in order to access fields of serializable classes. However, with JEP 471, the methods necessary to do this are being removed.

      Solution

      To allow these libraries to continue to function, it is proposed to add functionality to the sun.reflect.ReflectionFactory class (which is found in the jdk.unsupported module) which will allow serialization libraries to acquire method handles to generated readObject/writeObject methods which set or get the fields of the serializable class using the serialization GetField/PutField mechanism. These generated methods should be used by serialization libraries to serialize and deserialize classes which do not have a readObject/writeObject method or which use ObjectInputStream.defaultReadObject/ObjectOutputStream.defaultWriteObject to supplement default serialization.

      Also, add methods which allow for the reading of serialization-specific private static final fields from classes which have them.

      Specification

      Modify sun.reflect.ReflectionFactory to add the following API methods:

          /**
           * Generate and return a direct MethodHandle which implements
           * the general default behavior for serializable class's {@code readObject}.
           * The generated method behaves in accordance with the
           * Java Serialization specification's rules for that method.
           * <p>
           * The generated method will invoke {@link ObjectInputStream#readFields()}
           * to acquire the stream field values. The serialization fields of the class will
           * then be populated from the stream values.
           * <p>
           * Only fields which are eligible for default serialization will be populated.
           * This includes only fields which are not {@code transient} and not {@code static}
           * (even if the field is {@code final} or {@code private}).
           * <p>
           * Requesting a default serialization method for a class in a disallowed
           * category is not supported; {@code null} will be returned for such classes.
           * The disallowed categories include (but are not limited to):
           * <ul>
           *     <li>Classes which do not implement {@code Serializable}</li>
           *     <li>Classes which implement {@code Externalizable}</li>
           *     <li>Classes which are specially handled by the Java Serialization specification,
           *     including record classes, enum constant classes, {@code Class}, {@code String},
           *     array classes, reflection proxy classes, and hidden classes</li>
           *     <li>Classes which declare a valid {@code serialPersistentFields} value</li>
           *     <li>Any special types which may possibly be added to the JDK or the Java language
           *     in the future which in turn might require special handling by the
           *     provisions of the corresponding future version of the Java Serialization
           *     specification</li>
           * </ul>
           * <p>
           * The generated method will accept the instance as its first argument
           * and the {@code ObjectInputStream} as its second argument.
           * The return type of the method is {@code void}.
           *
           * @param cl a Serializable class
           * @return  a direct MethodHandle for the synthetic {@code readObject} method
           *          or {@code null} if the class falls in a disallowed category
           *
           * @since 24
           */
          public final MethodHandle defaultReadObjectForSerialization(Class<?> cl) { ... }
      
          /**
           * Generate and return a direct MethodHandle which implements
           * the general default behavior for serializable class's {@code writeObject}.
           * The generated method behaves in accordance with the
           * Java Serialization specification's rules for that method.
           * <p>
           * The generated method will invoke {@link ObjectOutputStream#putFields}
           * to acquire the buffer for the stream field values. The buffer will
           * be populated from the serialization fields of the class. The buffer
           * will then be flushed to the stream using the
           * {@link ObjectOutputStream#writeFields()} method.
           * <p>
           * Only fields which are eligible for default serialization will be written
           * to the buffer.
           * This includes only fields which are not {@code transient} and not {@code static}
           * (even if the field is {@code final} or {@code private}).
           * <p>
           * Requesting a default serialization method for a class in a disallowed
           * category is not supported; {@code null} will be returned for such classes.
           * The disallowed categories include (but are not limited to):
           * <ul>
           *     <li>Classes which do not implement {@code Serializable}</li>
           *     <li>Classes which implement {@code Externalizable}</li>
           *     <li>Classes which are specially handled by the Java Serialization specification,
           *     including record classes, enum constant classes, {@code Class}, {@code String},
           *     array classes, reflection proxy classes, and hidden classes</li>
           *     <li>Classes which declare a valid {@code serialPersistentFields} value</li>
           *     <li>Any special types which may possibly be added to the JDK or the Java language
           *     in the future which in turn might require special handling by the
           *     provisions of the corresponding future version of the Java Serialization
           *     specification</li>
           * </ul>
           * <p>
           * The generated method will accept the instance as its first argument
           * and the {@code ObjectOutputStream} as its second argument.
           * The return type of the method is {@code void}.
           *
           * @param cl a Serializable class
           * @return  a direct MethodHandle for the synthetic {@code writeObject} method
           *          or {@code null} if the class falls in a disallowed category
           *
           * @since 24
           */
          public final MethodHandle defaultWriteObjectForSerialization(Class<?> cl) { ... }
      
          /**
           * {@return the declared {@code serialPersistentFields} from a
           * serializable class, or {@code null} if none is declared, the field
           * is declared but not valid, or the class is not a valid serializable class}
           * A class is a valid serializable class if it implements {@code Serializable}
           * but not {@code Externalizable}. The {@code serialPersistentFields} field
           * is valid if it meets the type and accessibility restrictions defined
           * by the Java Serialization specification.
           *
           * @param cl a Serializable class
           *
           * @since 24
           */
          public final ObjectStreamField[] serialPersistentFields(Class<?> cl) { ... }

      The methods generated by default*ObjectForSerialization shall behave in accordance with the Java serialization specification to the extent that the generated methods conform to the specification given for user readObject and writeObject methods, as well as that given for ObjectInputStream#defaultReadObject and ObjectOutputStream#defaultWriteObject.

      It shall not be possible to access the interior fields of objects of classes which are not Serializable, or are Serializable but are also Externalizable, or qualify for certain types of special treatment by the Java serialization specification (including records, enum constants, Class, String, arrays, reflection proxy classes, hidden classes, and java.io.ObjectStreamFields, as well as any special types which may possibly be added to the JDK or the Java language in the future which in turn might require special handling by the provisions of that future version of the Java serialization specification). Any case where a default serialization method is requested for a class which falls under this disallowed category shall result in a null method handle being returned.

      Only fields which are accessible by the provisions of the serialization specification shall be accessed by the generated methods (this includes only fields which are both non-transient and non-static, even if they are public or otherwise would be accessible by Java language access rules).

      The serialPersistentFields method shall return the value of the corresponding serialPersistentFields field for any class which is Serializable but is not Externalizable, provided that the field meets the type and accessibility restrictions defined by the Java serialization specification. For any classes which do not meet these requirements, the method shall return null. Non-normatively, it is expected that the behavior of this method should be similar to that of ObjectStreamClass#getFields for cases where the class defines an explicit serialPersistentFields field.

            dmlloyd David Lloyd
            dmlloyd David Lloyd
            Alan Bateman, Roger Riggs
            Votes:
            0 Vote for this issue
            Watchers:
            6 Start watching this issue

              Created:
              Updated:
              Resolved: