<div dir="ltr"><div dir="ltr"><br></div><div dir="auto"><br><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Mar 28, 2024, 3:53 AM Remi Forax <<a href="mailto:forax@univ-mlv.fr" target="_blank">forax@univ-mlv.fr</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><div style="font-family:arial,helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)"><div><br></div><div><br></div><hr id="m_-68134697180072060m_-4987579851064815187zwchr"><div><blockquote style="border-left:2px solid rgb(16,16,255);margin-left:5px;padding-left:5px;color:rgb(0,0,0);font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt"><b>From: </b>"Shahan Yang" <<a href="mailto:shahan@google.com" rel="noreferrer" target="_blank">shahan@google.com</a>><br><b>To: </b>"amber-dev" <<a href="mailto:amber-dev@openjdk.org" rel="noreferrer" target="_blank">amber-dev@openjdk.org</a>><br><b>Sent: </b>Thursday, March 28, 2024 12:20:44 AM<br><b>Subject: </b>JEP 8323072 and Serialization</blockquote><div><br></div><div>Hello,</div><blockquote style="border-left:2px solid rgb(16,16,255);margin-left:5px;padding-left:5px;color:rgb(0,0,0);font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt"><br></blockquote></div><div><blockquote style="border-left:2px solid rgb(16,16,255);margin-left:5px;padding-left:5px;color:rgb(0,0,0);font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt"><div dir="ltr"><div>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.</div><br><div>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.</div><br><div>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.</div><br><div>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.</div><br><div>Do you have any suggestions? Am I overlooking something that other serialization libraries are doing here?</div></div></blockquote><div><br></div><div>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.<br></div><div>I think Brian as alreay proposes something quite similar for the Java serialization.<br></div></div></div></div></blockquote><div><br></div><div>Very well, thank you. Ironically, the serialization code started with that approach and quite a few classes are still serialized that way when reflection doesn't work. It's a bit more error prone and more toil which is why the reflection-based approach came into being. I guess we'll move back to constructor-based.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><div style="font-family:arial,helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)"><div><div><br></div><div>Why future-proof ?</div><div>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.</div></div></div></div></blockquote><div><br></div><div>Thank you for explaining this. Can't wait to see Valhalla.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><div style="font-family:arial,helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)"><div><div> <br></div><div><br></div><div>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.<br></div><div>But as i said above, it will be a short victory.<br></div><div><br></div><blockquote style="border-left:2px solid rgb(16,16,255);margin-left:5px;padding-left:5px;color:rgb(0,0,0);font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt"><div dir="ltr"><br><br><div>Thanks,</div><div>Shahan</div></div></blockquote><div><br></div><div>regards,<br></div><div>Rémi<br></div><div><br><br></div></div></div></div></blockquote></div></div>
</div>