Proposal: #ReflectiveAccessToNonExportedTypes: `exports dynamic`

mark.reinhold at oracle.com mark.reinhold at oracle.com
Fri Jul 1 17:10:55 UTC 2016


2016/7/1 1:48:07 -0700, Remi Forax <forax at univ-mlv.fr>:
> mark.reinhold at oracle.com:
>> ...
>> 
>> The nice thing about `exports dynamic` is that it lets you say "just
>> make the types in this package available for reflection by anybody, I'm
>> okay with that".
> 
> There are two differences between unqualified export and exports dynamic:
>  - exported types are only available at runtime not at compile time,
>  - exported types are available by anybody so a module like hibernate
>    doesn't have to requires a user module.

This second point is not correct: Using `exports dynamic` in a module
declaration does not mean that all other modules will automatically read
that module.  In module declarations, `exports` directives do not affect
readability; only `requires` does that.  Both normal, unqualified
exports and dynamic exports make the public types in a package available
to modules that read the exporting module.

In the case of a framework like Hibernate, which uses reflection, the
required readability will come "for free" thanks to the resolution of
the #ReflectionWithoutReadability issue [1] (your suggestion).

> I fail to see why these two guys are bundled together, i may want to
> have exported types available to anybody and visible at compile time.
> but i understand that having a way to say i want to export a package
> to anybody is interesting especially for library like hibernate.
> 
> Moreover, i don't like the fact that Java the language has a new way
> to interact with the reflection. The more we introduce such coupling
> the less we will be able to move in the future.

We've already introduced new ways for the language to interact with
reflection, in fact in the solution to #ReflectionWithoutReadability.

At any rate, the relationship between the language and the various
reflective APIs is, almost by definition, very intimate, so I don't
think we should be surprised that revisions to the language introduce
new interactions in this relationship.

Do you have specific examples in mind of undesirable coupling due to
this new interaction?

> so instead of exports dynamic i propose to introduce a way to say i
> want to export a package to anybody, an exports to * (star).
>   
> Using the example of the initial proposal, the module-info will be
> 
>     module com.foo.app {
>         requires hibernate.core;
>         requires hibernate.entitymanager;
>         exports com.foo.app.model to *;
>     }

This is exactly what `exports com.foo.app.model` already does today.
It exports the public types in that package to any module that reads
the `com.foo.app` module.  There's no need to add `to *`.

Whether some other module reads `com.foo.app` is, as I wrote above,
an issue that's orthogonal to whether and how any particular package
is exported, and in the case of reflective access is a non-issue since
reflection now simply assumes readability.

>> Remi Forax <forax at univ-mlv.fr>:
>>> ...
>>> 
>>> And it has several drawbacks, the main one is that it weaken the
>>> compiletime/runtime fidelity story, with a dynamic export the runtime
>>> world is not the compiletime world anymore.  The main motivation to
>>> add dynamic seems to be for backward compatibility during the
>>> transition between the classpath world and the full module world, for
>>> several other cases, we use the command line for that, i don't see why
>>> this case is so special that it should not work like the other
>>> compatibility issues.
>> 
>> Yes, it does weaken the fidelity story in order to accommodate existing
>> practice, but at least it does so in an explicit manner so that what's
>> going on is apparent just from reading the code.
>> 
>> I don't think, however, that this change is just about compatibility and
>> migration.  Even in an idealistic, Utopian, fully-modular world I expect
>> that we'll still want to use frameworks that use reflection on our own
>> types to help us be more productive.
> 
> yes, that's very true. Reflection allows to write meta object
> protocols but making a special case for the reflection seems wrong to
> me.

Just to be clear, the `exports dynamic` idea is motivated by existing
uses of reflection, but it's not intimately tied to reflection.  The
specification won't directly tie `exports dynamic` to the reflection
APIs.  Those APIs will, however, work more naturally as a consequence
of the semantics of `exports dynamic`, which will be defined entirely
in terms of the modular access-control concepts we already have.

- Mark


[1] http://openjdk.java.net/projects/jigsaw/spec/issues/#ReflectionWithoutReadability


More information about the jpms-spec-observers mailing list