Jason -- thanks for your feedback on this topic. To put what Alex wrote in a somewhat different way, I'd say that the tension here is between explicit configuration (as one finds today in, e.g., the Maven world) and implicit configuration (IoC). Both approaches are important. The former is typical of standalone Java SE applications while the latter is typical of Java EE applications, though the two approaches are often intermixed.
What we have in the design today seems to support the explicit approach pretty well, but we're still trying to figure out how best to support the implicit approach. If I understand correctly, your view of the present proposal is that: (1) It induces too much boilerplate, requiring developers to write `exports dynamic P` for every single package `P` that's subject to reflection by a framework, and (2) It weakens encapsulation too much, by making the types in such a package available for reflection at run time by any module in the system. These observations lead to your suggestion to allow declarative module boundaries to be overridden by "trusted" framework code. It's far from clear how to define such a facility in a way that would still allow us to achieve one of our primary goals, namely strong encapsulation, i.e., the ability of the author of a module to declare which types are accessible by other components, and which are not. I'd therefore like to explain and explore how the above issues can be addressed with the present design. * * * To point (1), we all know that the most common way for developers to write Java code today is with a rich and powerful IDE. These tools already have plenty of built-in cleverness for generating POJO classes, deriving precise `import` directives, and ameliorating other kinds of boilerplate. I don't think it would be at all a stretch for such tools to generate precise `exports dynamic` directives on demand, based upon the presence of IoC-style annotations, and maintain their consistency over time. Just as precise `import` directives in class and interface declarations document dependences upon specific types, so precise `exports dynamic` directives in a module declaration would document the exposition of specific types for reflection at run time. If we think it likely that some modules will need to export dozens or hundreds of packages, leading to extremely long module declarations, then one possible refinement would be to allow a wildcard: `exports dynamic *` would export all of a module's packages for reflection at run time. This would likely be straightforward. * * * To point (2), if some packages in a user module need to be exported for reflection at run time, and a container wishes to ensure that only select "trusted" framework modules can access the types in those packages, then that's already expressible today. We can also ensure that the set of packages exported by a module is the same whether it's used standalone on Java SE versus inside a container, which as you observe elsewhere in this thread [1] could be problematic. Suppose, e.g., we have an application module that's written against JPA, rather than any specific JPA implementation, and exports the package containing its entity classes for reflection at run time: module com.foo.data { requires java.persistence; exports dynamic com.foo.data.model; } When used standalone, outside of a container, this module will export the package containing its entity classes for reflection at run time. The classes will be accessible to every other module, but from a security and integrity standpoint we assume that whoever invokes the run-time system, i.e., whoever provides the command-line arguments to the `java` launcher or its equivalent, is trusted to ensure that no adversarial modules are present. When used inside a container, the container already has the power to prevent an adversarial module from accessing the module's entity classes. That's because we expect containers to load every application into a unique layer [2], and a container can rewrite module descriptors when configuring a layer. This is nothing to be ashamed of -- we fully expect it to become a common practice. If the container is set up to provide, e.g., Hibernate to this particular application, then it could narrow the accessibility of the entity classes by rewriting the above module declaration to refine the `exports dynamic` directive: module com.foo.data { requires java.persistence; exports dynamic com.foo.data.model to hibernate.core, hibernate.entitymanager; } (This is one of the very few use cases for qualified dynamic exports.) Whether standalone or in a container the same set of packages is exported by the module; the only difference is that, inside the container, the exports are qualified. * * * To sum up, for (1) I agree that unnecessary boilerplate is a bad thing. Asking the author of a module to be explicit about which packages are exported for reflection at run time, however, is of high value when trying to understand how the module fits into a larger system. The cost of such explicitness can, moreover, easily be reduced by the tools that almost all Java developers already use. For (2), I share your concern and I think it can be addressed within the scope of the present design. At this point I don't see a strong need to introduce a way to enable framework code to violate module boundaries arbitrarily at run time, and I don't know how to do that without, essentially, giving up on one of our primary goals. We could make it easier to rewrite module descriptors, by providing an API for that purpose rather than expecting container developers to use libraries such as ASM, and perhaps that's worth doing, but it's a different issue. - Mark [1] http://mail.openjdk.java.net/pipermail/jigsaw-dev/2016-July/008530.html [2] http://openjdk.java.net/projects/jigsaw/spec/sotms/#layers