Alternative mechanism for reflective access control (#ReflectiveAccessToNonExportedTypes / #AwkwardStrongEncapsulation)

Remi Forax forax at
Mon Sep 26 13:32:58 UTC 2016



----- Mail original -----
> De: "Stephen Colebourne" <scolebourne at>
> À: "jigsaw-dev" <jigsaw-dev at>
> Envoyé: Lundi 26 Septembre 2016 12:11:58
> Objet: Re: Alternative mechanism for reflective access control	(#ReflectiveAccessToNonExportedTypes /
> #AwkwardStrongEncapsulation)

> Having read this proposal a number of times, and considering how the
> talks explained things at JavaOne, I have come to the conclusion that
> this proposal is too complex. FWIW, I like the idea that a module
> should be able to declare that it needs reflective access from its
> users, however given that the proposal is what results from the idea,
> it doesn't seem as appealing as it should.
> The reason why I put forward the exports/exposes approach [1] is that
> it keeps the questions that must be asked when creating a module
> simple:
> - what do I depend on publicly (requires)
> - what do I publish publicly (exports)
> - what do I publish privately (exposes)
> From a security point of view it also seems that it should be the
> responsibility of a module to allow the publishing of its private
> details, and simply depending on another module seems very minimal
> (and easy to miss) as a mechanism to allow that extra permission.
> Stephen
> [1]
> On 21 September 2016 at 17:39, David M. Lloyd <david.lloyd at> wrote:
>> In our internal discussion of the proposal for
>> #ReflectiveAccessToNonExportedTypes, we discussed the ins and outs of
>> various behaviors and have come up with a few ideas or starting points for
>> solutions that we think would be more workable in conjunction with existing
>> middleware (ours and others').
>> For reasons previously explained, we do not think that weak modules are a
>> good way forward; I won't go into that again here.  But the logical
>> re-starting point is: If not weak modules, then what?
>> I will boil it down to a few basic requirements that we have established.
>> This list is probably non-exhaustive but hopefully complete enough to go on
>> for now:
>> • A module definition must be able to establish that a dependent has (or all
>> modules have) access to one or more (or all) packages for public reflection
>> only.
>> • A module definition must be able to establish that a dependent has (or all
>> modules have) access to one or more (or all) packages for public or private
>> reflection only.
>> • A module definition must be able to establish that a dependent has (or all
>> modules have) access to one or more (or all) packages for public reflection
>> and compilation/linkage (i.e. it's an export by today's terminology).
>> • A module definition must be able to establish that a dependent has (or all
>> modules have) access to one or more (or all) packages for public or private
>> reflection and compilation/linkage (i.e. it's a "private" export by today's
>> terminology).
>> • As today, any packages not declared in one or more of the above categories
>> is inaccessible outside of the module in any way (note that as I showed
>> previously we have also concluded that it should continue to be impossible
>> to export a package for compilation/linkage without public reflection, as we
>> have not discovered any use for such a mode).
>> More generally:
>> • The syntax for all of the above has no particular constraint (in fact I
>> will try to actively avoid touching what could be a very bikeshedding-rich
>> discussion), except that it should not be construable as being pejorative
>> against the usage of reflective frameworks; rather, it should be clear what
>> level of trust is being established without raising undue warning.
>> • Applications should not need gratuitous amounts of declarations in their
>> module(s) in order to utilize frameworks.
>> • As previously established, it should not be possible for one declaration
>> to reduce the scope of access of another declaration in a module definition.
>> • Access to a module (for reflective purposes only) must not cause conflicts
>> if multiple such modules which contain identical packages are accessible to
>> a single consumer; in other words, reflection-only access into
>> non-dependency modules is not bound by duplicate package restrictions as
>> long as each package is unique per class loader, as per the current (Java 8)
>> class loader rules.
>> The above cover the useful access modes that we have identified.  This is
>> _nearly_ adequate to cover the use cases that we are currently concerned
>> about; for example, I could export all packages for public reflection only
>> to a specific framework, if only I know the module name of the
>> implementation.
>> Unfortunately, this does not work well in the case where a module may
>> consume a framework whose specification is separate from the implementation.
>> An application module may need to use (say) EJB and JPA; there is presently
>> no clean way to do so without either (a) relying on a container environment
>> to rewrite the descriptor or (b) opening up the module and defeating the
>> security mechanism (e.g. "weak").  Without either of these workarounds, the
>> application developer must have a good deal of knowledge about what modules
>> provide what services within a framework-rich environment, possibly
>> resulting in a very verbose (and error-prone) descriptor; none of these
>> options is really satisfactory.
>> Thus, apart from the option of redesigning (to an extent) the security
>> mechanism (thereby eliminating the need to seal off access to public
>> reflection, which is definitely still an attractive option for various
>> reasons from our perspective, but which is also a very different
>> discussion), we need some sort of mechanism which decouples the literal
>> dependency system from access permission (much like uses/provides does).
>> For example if I could declare that my module uses "javax.ejb", and, in so
>> doing, automatically grants public and private reflective access to the
>> module that provides that service, this would be a good outcome.  A module
>> which answers to that service name could be responsible for reflective
>> access to the application module, providing that information privately to
>> any other framework modules which require it.
>> The migration story looks much better in this light: module descriptors
>> still can be quite terse and specific.  Applications which use reflective
>> frameworks do not need gratuitous exports; in fact it's much more fluid for
>> a user to say "I require these helper libraries; I use EJB; that's it" which
>> means they don't have to worry about the details of whatever particular
>> environment they run in.  This also has the advantage of allowing new Java
>> 9-generation specifications to stipulate standard service names for each
>> specification (e.g. "javax.ejb", "javax.cdi", that sort of thing).
>> While this doesn't cover 100% of our remaining issues with Jigsaw (of
>> course; we'll all continue moving through the issues list as we have been to
>> get us there), meeting these requirements would go a long way towards at
>> least having a reflection story that is more practical for present-day
>> frameworks to move forward with.  So the last requirement would be:
>> • A module definition must be able to establish that an "indirect"
>> dependency exists on an otherwise unknown module providing a capability,
>> wherein that module may require public or public+private reflection access
>> to some or all packages without compile/link access.  This could possibly
>> exist in conjunction with, or as an evolution of, the current services
>> mechanism, however a complicating factor is that the current mechanism is
>> based specifically on types, whereas a purely symbolic relationship might be
>> better for this purpose (this is not a requirement though if it can be made
>> to work as-is).  Note that any symbolic relationship system would need some
>> in-code discovery mechanism such that consumers of the capability are made
>> available to the provider and/or vice-versa, in order to make practical use
>> of the relationship.
>> The following example syntax is meant to be unambiguous and illustrative; no
>> specific attempt is made to reuse existing keywords (for example), or even
>> to imply an endorsement of the current descriptor mechanism at all, but to
>> clarify how this might look in practice and provide a practical application
>> of the ideas herein.
>> Example 1: A contrived provider of the fictional framework
>> "javax.fictional.orm" illustrating provides/uses-based access granting
>> module {
>>       // Require a module dependency, and give it private reflection access
>> to everything
>>       requires org.apache.commons.beanutils with private reflection on *;
>>       // Require a module dependency with no reflection
>>       requires org.apache.commons.logging;
>>       // Provide the framework
>>       provides javax.fictional.orm.ORM
>>           using private reflection
>>           with,
>>      ;
>> }
>> Example 2: A contrived consumer of #1
>> module com.mycompany.application {
>>       uses javax.fictional.orm.ORM; // automatically gives private
>> reflection
>> }
>> Example 3: Grant reflection access to a couple of packages to a named
>> non-dependency module
>> module com.mycompany.application {
>>       grant public reflection on
>>           com.mycompay.application.package1,
>>           com.mycompay.application.package2
>>       to;
>> }
>> Example 4: Behave like Java 8
>> module com.mycompany.application {
>>       grant private reflection on * to *;
>> }
>> Example 5: Behave like Java 8, but restrict private access without requiring
>> a security manager
>> module com.mycompany.application {
>>       grant public reflection on * to *;
>> }
>> Example 6: An example of using CDI and EJB with symbolic capabilities
>> module com.mycompany.application {
>>       uses capability javax.ejb, javax.cdi
>> }
>> Example 7: An example of providing EJB with symbolic capabilities
>> module {
>>       [...]
>>       provides capability javax.ejb using private reflection;
>> }
>> --
> > - DML

More information about the jigsaw-dev mailing list