5

The JLS 11 "7.7.2. Exported and Opened Packages" says:

It is permitted for opens to specify a package which is not declared by a compilation unit associated with the current module.

What would be a scenario for this? Why is this needed?

Mikhail Kholodkov
  • 23,642
  • 17
  • 61
  • 78
Barat Sahdzijeu
  • 1,683
  • 1
  • 18
  • 29
  • 1
    The JLS in next sentence says that this opens does not affect packages from other modules, so no hijacking: "(If the package should happen to be declared by an observable compilation unit associated with another module, the opens directive has no effect on that other module.)" so, your scenario probably does not fit. – Barat Sahdzijeu May 15 '19 at 11:05
  • From the JLS itself *Each observable compilation unit may be associated with a module, as follows: The host system may determine that an observable ordinary compilation unit is associated with a module chosen by the host system, except for the ordinary compilation units in the predefined package java and its subpackages lang and io, which are all associated with the java.base module. The host system must determine that an observable modular compilation unit is associated with the module declared by the modular compilation unit.* – Naman May 15 '19 at 11:37
  • @Naman, sorry, still not clear why one would open non-existing package? I see sun.reflect package belongs to jdk.unsupported. But what would be the reason to put "opens abc.xyz" in jdk.unsupported ? – Barat Sahdzijeu May 15 '19 at 12:52
  • Sorry, but it confuses me. (1) I still do not see reason to open non-existing package and (2) I am not sure "opens" is transitive, like "requires" (which must be done explicitly) – Barat Sahdzijeu May 15 '19 at 13:57
  • 3
    Think about a module that contains resources in their own "package". If you want other modules to be able to locate those resources then you'll need to open that package. – Alan Bateman May 15 '19 at 17:10
  • 1
    Alan, but the question is specifically about the situation that what is opened *doesn't* exist in the module. You're describing, as I read it, a perfectly reasonable situation, of course, but one in which the module *does* exist in that module. Or did I miss your intention? – Toby Eggitt May 15 '19 at 19:37
  • 3
    I think the issue here is "compilation unit" versus "resource". The quote from the JLS doesn't say that the package is non-existing: it says there are no compilation units. Consider the case where `config.properties` is stored in `com.foo.abc`. The package exists with entities to be exported but there are no compilation units (I'm assuming properties files aren't compilation units!) – Michael Easter May 16 '19 at 01:14
  • 1
    @MichaelEaster, OK, I understand your scenario. But in your scenario, the directory com/foo/abc must exist (we can consider it "package" or "resources folder", no matter) anyway (although with .properties file, not the .java file). I wonder why compilation succeeds when no com/foo/abc exists at all? I tried and this is a valid scenario. Is there any explanation/reason why this is allowed? – Barat Sahdzijeu May 16 '19 at 07:32
  • Just for the reference. The quoted JLS statement has been added since Java 9 - https://docs.oracle.com/javase/specs/jls/se9/html/jls-7.html#jls-7.7.2. This is not JLS 11 specific. – Mikhail Kholodkov May 16 '19 at 10:03
  • @MikhailKholodkov correct, and my question had java-9 tag initially, but was removed by moderator. It's from JPMS inception. – Barat Sahdzijeu May 16 '19 at 10:23

1 Answers1

3

Thanks to Alan Bateman and Michael Easter for explanations, and I can think of some realistic scenarios.

First, as was explained by Alan and Michael: JLS allows to "open" directories without Java types for situations when we keep resources in them. So, for us these are "resource directories", but JLS names it as package which is not declared by a compilation unit. And it's not even question of "allows" but rather "must". Without opens directive for resources directory (com/foo/abc), another module cannot read resource like that:

InputStream is = ClassLoader.getSystemResourceAsStream("com/foo/abc/config.properties");

Second, I wrote this question mostly because I was puzzled that opens allows to specify even non-existing "packages" (directories), although it gives warnings, but compiles successfully. A possible scenario behind that I can think of a build script for modular JAR file:

  1. it compiles .java files (we have module-info.java define opens com.foo.abc; and com/foo/abc directory ("package") does not exist)
  2. it creates com/foo/abc directory
  3. it copies there config_dev.properties file, at this step decision made for what environment we make build (PROD/TEST/DEV)
  4. JAR file is packaged, containing bytecode and resources.

In case opens for non-existing directory was not allowed, step #1 would fail. But it only gives a warning during compile time, which is Ok.

Barat Sahdzijeu
  • 1,683
  • 1
  • 18
  • 29