JEP 8323072 and Serialization

Remi Forax forax at univ-mlv.fr
Thu Mar 28 07:53:54 UTC 2024


> From: "Shahan Yang" <shahan at google.com>
> To: "amber-dev" <amber-dev at openjdk.org>
> Sent: Thursday, March 28, 2024 12:20:44 AM
> Subject: JEP 8323072 and Serialization
Hello, 

> My apologies if this is the wrong place for this kind of question. I maintain an
> Unsafe-heavy serialization library and I am weighing options in light of Unsafe
> memory access deprecation.

> It appears that the recommended replacement is to use VarHandles. This seems
> reasonable at first glance, but it looks like VarHandles do not support writes
> to final fields.

> The problem is that there's a large codebase with a lot of application logic
> objects to be serialized. The presence of final fields on those objects aids in
> their readability. Currently, those fields can just be set using Unsafe.put*
> methods during deserialization, but that isn't possible with VarHandles. I
> don't think it's reasonable to ask developers to make all of the application
> object fields non-final for deserialization. It would also be an infeasibly
> large amount of toil to add custom code to serialize and deserialize all those
> objects, relative to what is possible with reflection.

> I can think of a number of alternatives, but so far I haven't come up with
> anything that avoids harming the readability of the code, increasing toil,
> making serialization more error prone or slower (just using regular Field
> reflection instead of Unsafe to set final fields?). I'm less worried about
> records because the tight contract between their constructors and their fields
> makes a code generation-based solution quite clean.

> Do you have any suggestions? Am I overlooking something that other serialization
> libraries are doing here?

You ask for suggestions, my suggestion is that your serialization framework should ask users to provide the equivalent of a record canonical constructor, i.e. a constructor with the same visibility as the class that is able to initialize the class with either an annotation for each parameter that contains the corresponding name of the field or you can ask users to compile with "-parameters" then at runtime like with records, you just call that constructor. In my opinion, that's the simpler future-proof solution. 
I think Brian as alreay proposes something quite similar for the Java serialization. 

Why future-proof ? 
As part of Valhalla, we are introducing a new kind of fields, "really really final" fields that must be initialized *before* calling the super constructor and that can not be updated after the call to the super constructor. So even if we do not disable Unsafe.putField for those fields, the JIT is allowed to not use the result of an Unsafe.putField and use a previously seen value of the field. 

Otherwise, you can set the value of a final field by getting the field, calling setAccessible on it, then uses Lookup.unreflectSetter(field) on that field. You will get a method handle able to set a final field. 
But as i said above, it will be a short victory. 

> Thanks,
> Shahan

regards, 
Rémi 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-dev/attachments/20240328/65ab8018/attachment.htm>


More information about the amber-dev mailing list