I just want to point out the two obvious (closely related) major problems with this approach which prevent it from being a practical replacement for setAcceptable, lest they are forgotten/ignored in the excitement around the new ideas:

1. It requires the target class to be initialized
2. It requires the target class to proactively donate MethodHandles or a Lookup to the lookup class

Both of these are effectively pretty substantial usability regressions compared to the status quo. These problems are why I'd rather see some kind of static grant mechanism, and either a special static API to get an extra-privileged Lookup or the appropriate magic to allow a class's "normal" Lookup object to "see" everything that was granted to it; but really any idea which would solve both of these problems in any way should be put forward for consideration IMO.

On 10/31/2016 06:57 PM, Remi Forax wrote:
Hi Paul,
I think you can already sketch an implementation of the proposal now by using 
either an annotation processor + a jlink plugin, or by a jlink plugin + a 
bytecode processor tool.
I believe that you can push the information needed by the meta-framework to 
fulfill requests by adding some method calls inside the static initializer of 
the classes that are annotated.
The runtime part can be something along that line

https://gist.github.com/forax/1511fae2273f04273ff9463c6fbbdfbc

Instead of providing method handles as John suggests, i provide the lookup 
object which is less secure.
And the Class object in the map are stored as strong ref instead of being an 
ephemeron (the lambda used as value in the map has also a strong reference on 
the class).

Rémi

----- Mail original -----
De: "Paul Bakker" <paul.bak...@luminis.eu>
À: jigsaw-dev@openjdk.java.net
Envoyé: Lundi 31 Octobre 2016 18:06:27
Objet: Re: New proposal for #ReflectiveAccessToNonExportedTypes: Open   modules 
& open packages

The proposal looks very good! Thanks for listening to the voiced concerns.
When can we expect a new prototype containing the proposed features?

Thanks,

Paul

On Fri, Oct 28, 2016 at 3:38 PM John Rose <john.r.r...@oracle.com> wrote:

On Oct 27, 2016, at 9:07 AM, mark.reinh...@oracle.com wrote:

Further comments most welcome, as usual!


+100 for *qualified* opens; this puts an important limit on deep
reflection.

My main concern with reflection is to avoid "falling off the encapsulation
cliff"
the first time a user module wishes to open itself up for deep reflection.
By such a "cliff" I mean that when deep reflection is allowed, potentially
any name in the module can be inspected.  Even of only 0.01% of names
are actually inspected, tools for reorganizing code must assume that 100%
of the names *might* be inspected, at some point in the future, by the
allowed party.

So qualified opens is a partial solution.  And, I think it is exactly
right for
today, because it can be extended tomorrow.  I.e., it is future-friendly.
I'll explain by sketching a concept called "moderate reflection", or "MR".

A fuller solution would allow other tools to make conclusions about more
specific limitations on the actual extent of the deep reflection.   Call
such
an extent-limited reflection moderate reflection, where "moderation" is
declared statically by some sort of flexible declarative rule set.  In
this way
tools could make more detailed conclusions about the encapsulation of
particular names in the module.

 For future JDK releases we can consider layering  of this qualified opens,
by creating a trusted, parameterized meta-framework ("Moderate Reflection")
to which a user module can be qualified-open.  This meta-framework can
then perform deep reflection on behalf of self-describing "moderately
reflecting"
client frameworks.  User modules would not directly open themselves to any
module other than MR.

The advantage would come when the client frameworks explicitly declare
their
self-restraint ("moderation") in reflection.  For example, the "Foo"
framework
might limit itself to names annotated with @FooFrameworkHook.

An AOT compiler (or other jlink-time reorganization tool) would (1) note
that
some user module bar is qualified-open only to Moderate Reflection, and
has an export (maybe qualified) to a Foo framework.  At runtime, (2) the
Foo framework would ask Moderate Reflection to reflect into bar.
Moderate Reflection would (3) check the self-limitation on Foo, and also
ensure that bar exports (though doesn't open) to Foo.  MR would then
gain the requested access and delegate it back to Foo.  Finally, (4) the
AOT compiler would free itself to omit metadata for unexported names
not visible to moderate reflection.

(Method handles are a good way to grant access, since they can
be delegated from MR to Foo without re-authorizing Foo.  Core
Reflection re-authorizes on every access, which awkwardly
requires deep reflection on usage, as well as initial lookup.)

Moderate Reflection might also look at metadata on the bar module
(besides its module exports) to impose further limits on reflection.
Thus, MR-specific metadata might prevent MR from granting bar
access to normally-trusted frameworks that bar doesn't trust, if
bar can blacklist them for itself in a place that MR checks.

And so on.  None of this needs to be built into the module system.
To gain the benefit of it, basic parametric policies need to be
implemented,
adopted by client frameworks, and used by tools to perform optimizations.

A typical optimization is "tree shaking", where a class or method that is
never used is dropped from the application.  Or, if it is used in a way
that
can be inlined locally, the metadata can still be dropped.  In either case,
making code go dead is an important ingredient to many optimizations.

— John

--
- DML

Reply via email to