RFR: 8333796: Add missing serialization functionality to sun.reflect.ReflectionFactory

ExE Boss duke at openjdk.org
Fri Jul 5 14:46:45 UTC 2024


On Thu, 13 Jun 2024 14:31:06 GMT, David M. Lloyd <duke at openjdk.org> wrote:

> Issue [JDK-8164908](https://bugs.openjdk.org/browse/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 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.
> 
> To allow these libraries to continue to function, it is proposed to add two methods to `sun.reflect.ReflectionFactory` which will allow serialization libraries to acquire a method handle 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.
> 
> It is also proposed to add methods which allow for the reading of serialization-specific private static final fields from classes which have them.
> 
> With the addition of these methods, serialization libraries no longer need to rely on `Unsafe` for serialization/deserialization activities.
> cc: @AlanBateman

Since [JDK‑8331724], this can use the implementation classes in `jdk.internal.constant` to speed up default (de)serialization code generation startup.

[JDK‑8331724]: https://bugs.openjdk.org/browse/JDK-8331724

Relevant issue:
- https://github.com/openjdk/jdk/pull/15364

src/java.base/share/classes/jdk/internal/reflect/SerializationBytecodeGenerator.java line 55:

> 53:         // build an anonymous+hidden nestmate to perform the read operation
> 54:         List<MethodHandle> setters = new ArrayList<>();
> 55:         byte[] bytes = ClassFile.of().build(CD_Genearted_readObject, classBuilder -> classBuilder.withMethod("readObject",

Suggestion:

        byte[] bytes = ClassFile.of().build(CD_Generated_readObject, classBuilder -> classBuilder.withMethod("readObject",

src/java.base/share/classes/jdk/internal/reflect/SerializationBytecodeGenerator.java line 239:

> 237: 
> 238:     private static final ClassDesc CD_Generated_writeObject = ClassDesc.of("jdk.internal.reflect", "Generated$$writeObject");
> 239:     private static final ClassDesc CD_Genearted_readObject = ClassDesc.of("jdk.internal.reflect", "Generated$$readObject");

It might be better to use `ReferenceClassDescImpl​.ofValidated​(String)` here, or at least `ClassDesc​.ofDescriptor​(String)` to avoid binary to internal name conversion:

Suggestion:

    private static final ClassDesc CD_ObjectInputStream = ReferenceClassDescImpl.ofValidated("Ljava/io/ObjectInputStream;");
    private static final ClassDesc CD_ObjectInputStream_GetField = ReferenceClassDescImpl.ofValidated("Ljava/io/ObjectInputStream$GetField;");

    private static final ClassDesc CD_ObjectOutputStream = ReferenceClassDescImpl.ofValidated("Ljava/io/ObjectOutputStream;");
    private static final ClassDesc CD_ObjectOutputStream_PutField = ReferenceClassDescImpl.ofValidated("Ljava/io/ObjectOutputStream$PutField;");

    private static final ClassDesc CD_Generated_writeObject = ReferenceClassDescImpl.ofValidated("Ljdk/internal/reflect/Generated$$writeObject;");
    private static final ClassDesc CD_Generated_readObject = ReferenceClassDescImpl.ofValidated("Ljdk/internal/reflect/Generated$$readObject;");

src/java.base/share/classes/jdk/internal/reflect/SerializationBytecodeGenerator.java line 263:

> 261:     private static final MethodTypeDesc MTD_ObjectOutputStream_PutField_put_L = MethodTypeDesc.of(ConstantDescs.CD_void, ConstantDescs.CD_String, ConstantDescs.CD_Object);
> 262:     private static final MethodTypeDesc MTD_ObjectOutputStream_PutField_put_S = MethodTypeDesc.of(ConstantDescs.CD_void, ConstantDescs.CD_String, ConstantDescs.CD_short);
> 263:     private static final MethodTypeDesc MTD_ObjectOutputStream_PutField_put_Z = MethodTypeDesc.of(ConstantDescs.CD_void, ConstantDescs.CD_String, ConstantDescs.CD_boolean);

Using `MethodTypeDescImpl​.ofTrusted(…)` or at least `MethodTypeDescImpl​.ofValidated(…)` here avoids array copying:
Suggestion:

    private static final MethodTypeDesc MTD_ObjectInputStream_readFields = MethodTypeDescImpl.ofValidated(CD_ObjectInputStream_GetField);

    private static final MethodTypeDesc MTD_ObjectInputStream_GetField_get_B = MethodTypeDescImpl.ofValidated(ConstantDescs.CD_byte, ConstantDescs.CD_String, ConstantDescs.CD_byte);
    private static final MethodTypeDesc MTD_ObjectInputStream_GetField_get_C = MethodTypeDescImpl.ofValidated(ConstantDescs.CD_char, ConstantDescs.CD_String, ConstantDescs.CD_char);
    private static final MethodTypeDesc MTD_ObjectInputStream_GetField_get_D = MethodTypeDescImpl.ofValidated(ConstantDescs.CD_double, ConstantDescs.CD_String, ConstantDescs.CD_double);
    private static final MethodTypeDesc MTD_ObjectInputStream_GetField_get_F = MethodTypeDescImpl.ofValidated(ConstantDescs.CD_float, ConstantDescs.CD_String, ConstantDescs.CD_float);
    private static final MethodTypeDesc MTD_ObjectInputStream_GetField_get_I = MethodTypeDescImpl.ofValidated(ConstantDescs.CD_int, ConstantDescs.CD_String, ConstantDescs.CD_int);
    private static final MethodTypeDesc MTD_ObjectInputStream_GetField_get_J = MethodTypeDescImpl.ofValidated(ConstantDescs.CD_long, ConstantDescs.CD_String, ConstantDescs.CD_long);
    private static final MethodTypeDesc MTD_ObjectInputStream_GetField_get_L = MethodTypeDescImpl.ofValidated(ConstantDescs.CD_Object, ConstantDescs.CD_String, ConstantDescs.CD_Object);
    private static final MethodTypeDesc MTD_ObjectInputStream_GetField_get_S = MethodTypeDescImpl.ofValidated(ConstantDescs.CD_short, ConstantDescs.CD_String, ConstantDescs.CD_short);
    private static final MethodTypeDesc MTD_ObjectInputStream_GetField_get_Z = MethodTypeDescImpl.ofValidated(ConstantDescs.CD_boolean, ConstantDescs.CD_String, ConstantDescs.CD_boolean);

    private static final MethodTypeDesc MTD_ObjectOutputStream_putFields = MethodTypeDescImpl.ofValidated(CD_ObjectOutputStream_PutField);

    private static final MethodTypeDesc MTD_ObjectOutputStream_PutField_put_B = MethodTypeDescImpl.ofValidated(ConstantDescs.CD_void, ConstantDescs.CD_String, ConstantDescs.CD_byte);
    private static final MethodTypeDesc MTD_ObjectOutputStream_PutField_put_C = MethodTypeDescImpl.ofValidated(ConstantDescs.CD_void, ConstantDescs.CD_String, ConstantDescs.CD_char);
    private static final MethodTypeDesc MTD_ObjectOutputStream_PutField_put_D = MethodTypeDescImpl.ofValidated(ConstantDescs.CD_void, ConstantDescs.CD_String, ConstantDescs.CD_double);
    private static final MethodTypeDesc MTD_ObjectOutputStream_PutField_put_F = MethodTypeDescImpl.ofValidated(ConstantDescs.CD_void, ConstantDescs.CD_String, ConstantDescs.CD_float);
    private static final MethodTypeDesc MTD_ObjectOutputStream_PutField_put_I = MethodTypeDescImpl.ofValidated(ConstantDescs.CD_void, ConstantDescs.CD_String, ConstantDescs.CD_int);
    private static final MethodTypeDesc MTD_ObjectOutputStream_PutField_put_J = MethodTypeDescImpl.ofValidated(ConstantDescs.CD_void, ConstantDescs.CD_String, ConstantDescs.CD_long);
    private static final MethodTypeDesc MTD_ObjectOutputStream_PutField_put_L = MethodTypeDescImpl.ofValidated(ConstantDescs.CD_void, ConstantDescs.CD_String, ConstantDescs.CD_Object);
    private static final MethodTypeDesc MTD_ObjectOutputStream_PutField_put_S = MethodTypeDescImpl.ofValidated(ConstantDescs.CD_void, ConstantDescs.CD_String, ConstantDescs.CD_short);
    private static final MethodTypeDesc MTD_ObjectOutputStream_PutField_put_Z = MethodTypeDescImpl.ofValidated(ConstantDescs.CD_void, ConstantDescs.CD_String, ConstantDescs.CD_boolean);

-------------

PR Review: https://git.openjdk.org/jdk/pull/19702#pullrequestreview-2149053446
PR Comment: https://git.openjdk.org/jdk/pull/19702#issuecomment-2175793616
PR Review Comment: https://git.openjdk.org/jdk/pull/19702#discussion_r1659368798
PR Review Comment: https://git.openjdk.org/jdk/pull/19702#discussion_r1659368645
PR Review Comment: https://git.openjdk.org/jdk/pull/19702#discussion_r1659372351


More information about the core-libs-dev mailing list