New proposal for #ReflectiveAccessToNonExportedTypes: Open modules & open packages
Remi Forax
forax at univ-mlv.fr
Mon Oct 31 23:57:47 UTC 2016
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.bakker at luminis.eu>
> À: jigsaw-dev at 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.rose at oracle.com> wrote:
>
>> On Oct 27, 2016, at 9:07 AM, mark.reinhold at 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
More information about the jigsaw-dev
mailing list