The rationale for runtime modularization

mark.reinhold at mark.reinhold at
Fri Dec 4 00:19:30 UTC 2015

2015/12/3 1:36 -0800, Rafael Winterhalter <rafael.wth at>:
> I am writing this after looking into Jigsaw for about two months and after
> running my open-source libraries and several enterprise applications of my
> current employer using the EA builds.

Glad to hear it!

> In the context of these experiences, I wanted to ask for the rationale of
> project Jigsaw to enforce modularization at runtime.

Short answer: Strong encapsulation at run time greatly improves both
security and maintainability.  (Strong encapsulation at compile time
makes it much easier to prepare for strong encapsulation at run time.)

> In the software I have searched, reflection is predominantly used for
> interacting with code that is unknown during compilation. Of course,
> sometimes reflection is used for abstracting code from types but this is
> extremely rare as generic types pretty much cover this need.
> In practice, this implies that any reflective invocation requires an
> explicit module check. This check can be easily forgotten.

The failure in this case should be easy to diagnose, and the remedy
would be to invoke the Module::addReads method.  (If the target module
doesn't export the relevant package then you'll need to arrange for that
too, either via a command-line flag or possibly by some more convenient
means yet to be devised.)

>                                                            Furthermore, the
> compiler does not remind of missing edges when migrating software either.
> It seems to me that the assumption for the runtime checks is that
> invocations might accidentally cross module boundaries.

The checks performed by the reflection APIs themselves are intended to
match those performed by the compiler and the VM for non-reflective
operations, so whether accidental or not a reflective attempt to break
encapsulation will be caught.

>                                                         From the code that
> I looked at, I argue that this is already the primary intention when using
> reflection.

Yes, it's probably more common to use reflection to access types in
other modules rather than in the same module.

> One might argue that the same holds for reflection on non-public types.
> However, in this case I believe that security concerns are the main reason
> for enforcing accessability where access can be denied by a security
> manager.

That concern also applies to public types which are not meant to be used
in unintended ways -- and there are lots of those, both in the JDK and
in general.

>          Modules on the other hand cannot provide additional security as
> there is always an opt-out for non-modularized code to avoid such barriers.

Non-modularized code can only break through module barriers if explicit
permission is given for that, on the command line.  So yes, there's an
opt-out mechanism, but it forces the end user to be aware that the
system as a whole will run with compromised integrity.

> I am sure this possibility was considered and I wonder why it was not
> implemented. Looking at the very little practical relevance of heap
> pollution caused by type-erasure, I believe that compile-time
> modularization would work well in this case, too. The Java compiler could
> enforce module boundaries while users of reflection would not be bothered
> with the boundaries they intended to cross in the first place. As the most
> important benefit, migration would be much easier. Libraries could add
> module descriptors to pre-Java-9 bundles without needing to alter code
> since runtime behavior does not longer depend on the bundling format.

If strong encapsulation is to mean anything then it must be enforced at
run time, so a purely compile-time approach is just not viable.  (One
could argue that we already have compile-time modularization today, with
build tools such as Maven, in which case if compile-time modularization
were sufficient then we never would've started this project.)

It's become clear from all the recent feedback that the current design
might be making life a bit too hard for framework libraries that make
heavy use of reflection, so as I indicated in a nearby thread we're
definitely going to look into ways to address that.

- Mark

More information about the jigsaw-dev mailing list