Proposal: #ReflectiveAccessToNonExportedTypes: `exports dynamic`
Volker Berlin
volker.berlin at goebel-clan.de
Thu Jun 30 20:09:41 UTC 2016
Reflection should be enabled by default. My current launcher for Java 9
check if the needed refection is possible. If not possible then it
restart the application with a very long list of -XaddExports switches.
I think this is not what we want.
Volker Berlin
i-net software
Am 28.06.2016 um 23:18 schrieb Mark Reinhold:
> Issue summary
> -------------
>
> #ReflectiveAccessToNonExportedTypes --- Some kinds of framework
> libraries require reflective access to members of the non-exported
> types of other modules; examples include dependency injection (Guice),
> persistence (JPA), debugging tools, code-automation tools, and
> serialization (XStream). In some cases the particular library to be
> used is not known until run time (e.g., Hibernate and EclipseLink both
> implement JPA). This capability is also sometimes used to work around
> bugs in unchangeable code. Access to non-exported packages can, at
> present, only be done via command-line flags, which is extremely
> awkward. Provide an easier way for reflective code to access such
> non-exported types. [1]
>
> Proposal
> --------
>
> Extend the language of module declarations so that a package can be
> declared to be exported at run time but not at compile time. This is,
> roughly, the dual of the `requires static` construct proposed for
> #CompileTimeDependences, hence we propose to introduce a new modifier,
> `dynamic`, for use on the `exports` directive. It has the following
> meanings:
>
> - At compile time, `exports dynamic P` does not cause the package `P`
> to be exported, though it does require `P` to be a package defined
> in the module.
>
> - In phases after compile time, `exports dynamic P` behaves in exactly
> the same way as `exports P`. It therefore takes part fully in
> resolution and configuration, and is subject to the same consistency
> constraints as normally-exported packages (e.g., no split packages).
>
> Thus a module declaration of the form
>
> module com.foo.app {
> requires hibernate.core;
> requires hibernate.entitymanager;
> exports dynamic com.foo.app.model;
> }
>
> makes the types in the `com.foo.app.model` package accessible at run time
> but not at compile time. In combination with the earlier change to
> enable #ReflectionWithoutReadability [2] this means that frameworks that
> today use core reflection to manipulate user classes at run time are more
> likely to work out-of-the-box, without change, as automatic modules. If
> the `com.foo.app.model` package in this example includes entity classes
> to be managed by Hibernate then the framework will be able to access them
> without further ado, but under normal circumstances an attempt to compile
> code that refers directly to those classes will fail.
>
> The `dynamic` modifier can be applied to both unqualified and qualified
> `exports` directives, though the caveats on using qualified exports [3]
> still apply.
>
> Notes
> -----
>
> - To access a non-public member in a dynamically-exported package you
> must still invoke the appropriate `setAccessible` method, just as
> you do today to access non-public members in an exported package.
>
> - This proposal is similar to Rémi's suggestion to add a way to export
> a package only for reflection, still requiring that `setAccessible`
> be invoked [4]. This proposal differs in that it does not require
> `setAccessible` to be invoked to access public members in a
> dynamically-exported package.
>
> - This proposal primarily addresses "friendly" uses of reflection, such
> as dependency injection and persistence, in which the author of a
> module knows in advance that one or more packages must be exported at
> run time for reflective access by frameworks. This proposal is also
> convenient for frameworks that generate code at run time, since the
> constant pool of a generated class file can include static references
> to types in dynamically exported packages.
>
> - This proposal opens the door to a category of second-class APIs. If
> a package is exported dynamically then you can still compile code
> that refers to types in the package, by using `-XaddExports` or its
> equivalent at compile time, and it will work as expected at run time.
> It thus may be useful to use `exports dynamic` for packages that
> contain legacy APIs whose use is strongly discouraged, e.g., those in
> the `jdk.unsupported` module of the reference implementation, thereby
> forcing anyone who wants to compile against them to go to the trouble
> of using `-XaddExports`.
>
> - Intrusive access to arbitrary packages of arbitrary modules by, e.g.,
> debugging tools, will still require the use of sharp knives such as
> the `-XaddExports` command-line option or its equivalent, or JVM TI.
>
> - Using the `-XaddExports` option or its equivalent remains awkward,
> and sometimes it's the only way out. To ease migration I think it's
> worth considering some way for an application packaged as a JAR file
> to include such options in its `MANIFEST.MF` file, as suggested by
> Simon Nash [5]. I'll create a separate issue for that.
>
> - New kinds of resolution failures are possible. If module `A`
> requires `B`, and `B` requires `C`, then if `B` and `C` both declare
> some package `P` to be exported dynamically, then a split-package
> error will be reported. This may surprise, since the packages are
> just internal implementation details that were exported dynamically
> so that some framework could access their types. This is not,
> however, all that different from the kinds of resolution and
> layer-creation failures that are already possible due to package
> collisions. It's unlikely to happen all that often in practice,
> and the fix is straightforward: Just use reverse-DNS or otherwise
> sufficiently-unique package names, as most people already do. It
> is worth exploring whether javac can detect at least some of these
> kinds of collisions and issue appropriate warnings.
>
>
> [1] http://openjdk.java.net/projects/jigsaw/spec/issues/#ReflectiveAccessToNonExportedTypes
> [2] http://openjdk.java.net/projects/jigsaw/spec/issues/#ReflectionWithoutReadability
> [3] http://openjdk.java.net/projects/jigsaw/spec/sotms/#qualified-exports
> [4] http://mail.openjdk.java.net/pipermail/jpms-spec-experts/2015-December/000205.html
> [5] http://mail.openjdk.java.net/pipermail/jigsaw-dev/2015-December/005745.html
>
More information about the jpms-spec-observers
mailing list