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