Proposal: #ReflectiveAccessToNonExportedTypes: `exports dynamic`
mark.reinhold at oracle.com
mark.reinhold at oracle.com
Thu Jun 30 00:35:59 UTC 2016
2016/6/29 1:51:16 -0700, Remi Forax <forax at univ-mlv.fr>:
> I would like to agree on that proposal only on the ground that it
> requires to change the classfile format thus allows in the same time
> to fix the issues of the current classfile spec (encoding of the name
> module as a Class instead of UTF8, wrong flag for requires public),
I think that these are completely distinct issues (though your
class-file issues are not yet in the issue list -- would you care
to suggest some text?).
> but i'm not sure this proposal support it's own weight.
> Without dynamic, a 'classical' export works the same way at runtime so
> adding 'dynamic' to an export only restrict the usage at compile time.
> Given that we can already selectively export packages to some chosen
> modules which hide them for the rest of the other modules at compile
> time, adding dynamic to the spec adds little value.
Qualified exports aren't really a satisfactory substitute for dynamic
exports. They still export packages at compile time, thereby tempting
unwanted usage. They're also really meant only for use within a group
of tightly-associated modules, where hashing can be used to ensure
integrity, rather than amongst unrelated modules, between which names
can all too easily be spoofed.
More to the point, qualified exports are not adequate for all use cases.
If you want to write a module that uses JPA but is independent of JPA
implementation then you'll need to make your entity classes available
to whichever JPA implementation you do wind up using (Hibernate or
EclipseLink or ...), but you don't know the name of that
implementation's module. In other words, you can't write
exports com.foo.app.model to jpa;
because `jpa` is not an actual module, it's a stand-in.
We could introduce a level of indirection so that you could do that sort
of thing, say some notion of "abstract module", but that'd be a very,
very deep change and it doesn't fit at all well with existing practices
around JAR files.
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".
> 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.
> Moreover, an agent, an annotation processor and a jlink plugin are all
> able to implement the same trick, add export after the compilation and
> before the runtime, so i don't think it's a good idea to change the
> spec for that.
Then how do you express, in your source code, that you want an export to
be added at run time?
You could use an annotation, but that would require anybody who wants
to do this sort of thing to configure their environment to include the
module that defines that annotation and to add the required annotation
processor at the appropriate point. Do we really want to tell people
to do that when we can solve the problem for them so simply?
More information about the jpms-spec-observers