Towards better serialization
brian.goetz at oracle.com
Sun Jun 16 23:14:14 UTC 2019
> While I agree that the proposed usage of `open` would be a natural extension of the existing concept, I was always under the impression that `open` was intended as a “temporary" migration aid. That frameworks were supposed to move away from reflection and adopt solutions based on `MethodHandles.Lookup` instead. So I'm surprised to see the use of reflection promoted now.
- First, don't take the paper as something written in stone; it is a
first draft. (A first draft that reflects hundreds of hours of analysis
(if not more) by multiple people over multiple years, but a first draft
nonetheless. This is just the first version that reached a level of
"doesn't suck" sufficient that it was good enough to share publicly, but
I have no illusions that this is in any sense "done" -- it's more that
we have finally arrived at the starting line.) Accordingly, the
specifics of how fine-grained the relaxation mechanism, are a stake in
the ground -- the high order bit here is "there should be some way to
identify individual methods as having different dynamic accessibility as
static accessibility, allowing private methods in private classes in
non-exported packages to still somehow be callable dynamically -- based
on an explicit indication in the source." The exact details are to be
determined. Similarly, whether exposed via classic reflection vs Lookup
is a detail to be determined.
- I think you may have over-rotated towards the "reflection is dead"
meme. Yes, Lookup is "better" because it is explicit, and allows the
access checks to be done at lookup time rather than on each invocation.
But, reflection does things that Lookup does not (or at least, not yet);
you can't iterate over the methods of a class via a Lookup, let alone
interrogate them for their annotations, or query their Signature
attributes, or any number of other things frameworks like to do. So it
is likely that frameworks will be using reflection for quite a while,
and that's OK.
> An advantage of open packages, is that they are able to specify whom they're exporting to. So I can say: `opens foo.ser to some.ser.framework` and `opens foo.cdi to some.cdi.framework`.
There's a pretty broad spectrum of granularity possible here. On the
one extreme, you could just say "we don't need open methods, we have
open packages -- if you want to serialize, open the package." On the
other extreme, you could say that open methods are way too coarse
grained; they tar serialization frameworks and dependency injection
frameworks and mocking frameworks with the same brush. And there's a lot
in the middle.
There's also a danger that the search for more accurate permission
granularity becomes a rathole; for example, the security manager
permissions model is quite fine-grained, but in reality people rarely
use that mechanism to tailor just the right security policy -- it's too
hard, too fussy, too much work, too hard to keep it in sync with what
the code actually needs. So while we might over time attempt to put
more structure on "back door APIs", this is probably a good starting
Further, putting "opens X to Y" in the source code may actually require
us to name Y before we actually know it; when you're writing a library
class, do you really know which serialization frameworks the application
into which your library is incorporated will be using? This seems more
an issue for application assembly time -- Y is often only known when the
entire application is put together -- than of component development
time. But if the `opens` clause is in the source file, we only know
what is known at component development time.
So, yes, there are likely to be more mechanisms to model accessibility
on the backdoor API (including, probably, the ability to say things like
"I know there are methods in module X that are open, but I still want
them encapsulated in MY application") -- but I think its premature at
this stage to try to design them now.
More information about the amber-dev