Could we get module-private visibility?

Mike Hearn mike at plan99.net
Tue Sep 24 15:24:16 UTC 2019


Hello,

Often you want a method or constructor to be private to your module. The
closest approximation for this today is package-private, but this isn't an
ideal match. Kotlin has the "internal" modifier, which makes the modified
element be visible only inside a module. This is simple and often what you
want if you have small modules (which Jigsaw makes much more practical),
however, the JVM doesn't understand it so it's not enforced for other
languages or in reflection/sandboxing.

Using package-private correctly can be tricky. Using Kotlin's notion of
internal is even worse because it gets mapped to public, so in effect the
entire Java ecosystem ignores it.

I think the underlying issue is that packages do a lot of work. They
provide at minimum:

   1. Better organisation of an API in JavaDocs, so types can be given
   descriptions and broken up to make exploration easier for users.
   2. Organisation of a codebase for developers who work on it, to stop
   their IDEs being overwhelmed with giant lists of classes.
   3. An abstraction boundary, so implementation details can be hidden from
   the API user.
   4. A sandboxing boundary, so capabilities can be implemented more easily.
   5. A VCS access control boundary, because they map to directories and
   many version control systems let developers own directories.
   6. An IDE autocomplete boundary, so you can glob import and get better
   auto completion.

So it's not surprising that they get used in various different ways. The
JDK is filled with weird "secrets" classes that exist mostly because of
mismatches between what level of visibility is needed vs provided.
Nestmates have helped mop up some tech debt in this area, but what's
offered to users hasn't changed much. Writing code for sandboxed usage is
hard when you simultaneously want e.g. one package per backend of your API
but also need those backends to access internal methods in top-level
generic API classes. Calls cross package boundaries so package-private
isn't quite right.

An internal modifier like Kotlin's but supported by the JVM would help a
lot for crafting good APIs.

Alternatively, an interesting move might be to do invokedynamic but in
reverse: allow methods/c'tors/fields in class files to declare other
methods as 'guards' which decide at runtime if a link should be allowed or
not. Then languages can implement whatever visibility rules they want in
their standard library, and more of the JVM's linker logic can be moved
into Java itself.


More information about the jigsaw-dev mailing list