8

Various resources (infoq, jigsaw-dev, osdir) indicate that having the same package in different java modules will lead to a LayerInstantiationException, even when the packages are internal to the module (non-exported).
This seems to be the exact opposite of what the requirements say :

The Java compiler, virtual machine, and run-time system must ensure that modules that contain packages of the same name do not interfere with each other. If two distinct modules contain packages of the same name then, from the perspective of each module, all of the types and members in that package are defined only by that module.

So are (will) two modules used by an app be able to contain private packages of the same name ?

EDIT
This is an issue of JMPS as pointed by Stanislav Lukyanov

Naman
  • 27,789
  • 26
  • 218
  • 353
Bax
  • 4,260
  • 5
  • 43
  • 65

2 Answers2

7

As said in the discussions you've linked, the issue is about mapping between class loaders and modules.

When you're loading two modules M1 and M2 both containing a non-exported (a.k.a. concealed) package P via a class loader CL JPMS has to reject such configuration, since otherwise both key JPMS principles - strong encapsulation and reliable configuration - could be broken. By throwing an exception here JPMS actually implements the requirement you've quoted and ensures that no conflicts may break anything later during the execution.

On the other hand, when you're loading M1 and M2 via two loaders CL1 and CL2 you're actually creating two run-time packages {CL1, P} and {CL2, P}, so there is no collision and the Layer can be instantiated.

The usability problem here is that java uses single loader for all modules of the application layer (the "starting" one, created from the command-line arguments) which leads to the LayerInstantiationException. That's currently an open issue on the JPMS list, see [here] (http://openjdk.java.net/projects/jigsaw/spec/issues/#AvoidConcealedPackageConflicts). But regardless of the issue's resolution, if needed, you should be able to deal with the split packages by writing a tiny main class that will create the Configuration you need (BTW a JPMS-aware application container will probably do it for you).

Stanislav Lukyanov
  • 2,147
  • 10
  • 20
1

This definition is open to interpretation. It remains correct as Jigsaw ensures that two modules never define shared packages by crashing the class loading in case of such a conflict.

If you look into Java 9's class loader implementation, you can see that a package name is mapped by to a single module. Its therefore impossible two have two modules to declare ownership. It is however possible that two class loaders in child-parent relationship define the same package.

Rafael Winterhalter
  • 42,759
  • 13
  • 108
  • 192
  • I'd say the two class loaders should not be in child-parent relationship because to me that means the child will first ask the parent for the class/package and only then try to load it on his own (or vice versa) – Bax Nov 16 '16 at 17:04
  • 1
    To avoid this, Java 9 has deprecated the `getPackage` method in favor of the `getDefinedPackage` method. The same package name by two different class loaders are not considered equal even today; if you for example subclass A from B, B cannot override package-private methods of A if it was loaded in a different class loader. If the parent does not define the same class (!), there is no problem if they use the same package as its not equal. This problem only arises if packages are defined by two modules within the same class loader. – Rafael Winterhalter Nov 18 '16 at 09:33
  • is every module loaded by a different class loader by default ? – Bax Feb 06 '18 at 22:23
  • No. By default, all user classes and all system classes are loaded by the two same class loaders. – Rafael Winterhalter Feb 07 '18 at 06:34
  • Which means the problem arises by default an not *only if* – Bax Feb 07 '18 at 16:30