New proposal for #ReflectiveAccessToNonExportedTypes: Open modules & open packages
Remi Forax
forax at univ-mlv.fr
Tue Nov 1 12:12:10 UTC 2016
----- Mail original -----
> De: "Remi Forax" <forax at univ-mlv.fr>
> À: "Paul Bakker" <paul.bakker at luminis.eu>
> Cc: jigsaw-dev at openjdk.java.net
> Envoyé: Mardi 1 Novembre 2016 00:57:47
> Objet: Re: New proposal for #ReflectiveAccessToNonExportedTypes: Open modules & open packages
> 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).
After shower edit,
i've updated the gist to use a ClassValue + a CAS so there is no strong ref to the classes now.
>
> Rémi
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