Towards better serialization
brian.goetz at oracle.com
Thu Jun 13 18:25:03 UTC 2019
> I don't know that it's necessary to remove the old serialization. It works just fine for symmetric serialization (a controlled environment where you can guarantee the reader and writer use the exact same code). Under that constraint, it actually delivers on its promise. It's just that it's dangerous for almost anything else.
Yes. And, note as well that it is not all-or-nothing; we can “demote” default serialization without disabling it, by (say) requiring an opt-in (e.g., —enable-default-unsafe-legacy-serialization-yes-i-know) so that applications that want to use it can, and applications that don’t can be protected from it. There’s a huge range of policy choices here, which can be phased in over time.
There are two parts to the approach outlined here:
- Upgrading the programming model to allow authors to have explicit but unobtrusive control over extracting state from objects, reconstituting them safely, and capturing schema evolution;
- Adjusting Java serialization (and other serialization frameworks) to use this mechanism.
The first is obviously a precursor to the second, but within the second, there is a range of policy choices, which can play out over time, and different serialization frameworks can make different choices.
> The main thing that I have a problem with is `open`. It seems we are turning 4 visibility levels into a 4x2 matrix (with one cell, `public open`, being redundant) ... and just because of reflection? This feels wrong to me. It might be what we need, but I would really like to know that we've exhausted all alternatives. Again, though, this is a tree. The forest is good.
Actually, “public open” may not actually be redundant; “public open” in a non-exported package of a module is only statically public within the module.
But again, this is a tree, so let’s talk about the forest: the distinction between “front door” and “back door” APIs is real. Backdoor APIs include serialization, but they also include members that exist to support, say, mocking or dependency injection.
While the “backdoor” API members are effectively public, we don’t necessarily want to expose them statically to front-door consumers, because they are not intended for front-door consumers. The module system has recognized this need, where a package can be opened but not exported, allowing for dynamic access but not static access. We can piggyback on this (if a module is open, it is not actually required to open the individual members, though doing so has benefit to readers anyway), but opening an entire module for the sake of serializing a few classes is a pretty coarse hammer.
I see a lot of benefit in using the _same_ mechanism to segregate front-door and back-door API members at the different granularities (member, class, package, module) rather than inventing different ones, but that’s a possibilities too. Another possibility is to break the 4x2 down into 4+1, where “open” implies “statically private”.
More information about the amber-spec-observers