"opens" is a superset of "exports".

-----Original Message-----
From: Alexander Udalov [mailto:alexander.uda...@jetbrains.com] 
Sent: Friday, September 15, 2017 8:14 AM
To: jigsaw-dev <jigsaw-dev@openjdk.java.net>
Subject: "exports" directive does not open module's resources for dependent 
modules

It looks like exporting a package from a (non-open) module with an "exports" 
directive is not enough to ensure that Module.getResourceAsStream on that 
module would load resources from the module. Surprisingly, adding an "opens" 
directive for the same package to the module declaration allows resources to be 
found.

I've put up a simple project to demonstrate this issue:
https://github.com/udalov/jigsaw-resources-are-not-exported

I'm wondering whether this is a bug or expected behavior? I would expect that 
exporting a package would also open it not only for uses of reflection, but for 
resource loading. I can't find anything related to resources in the JLS, but 
p.7.7 "Module Declarations" gives a clear impression that the "exports" 
directive gives a superset of functionality of the "opens" directive in this 
regard.

Looking at the implementation of Module.getResourceAsStream, I see that it 
calls Module.isOpen(String, Module) which returns false in case the package 
name is exported by an "exports" directive. Which raises another question: is 
Module.isOpen supposed to return whether the package has been explicitly opened 
by an "opens" directive (or via being in an open module)? Or is it supposed to 
also return true if the package has been opened as a consequence of the fact 
that it's exported (e.g. by an "exports" directive)? If the former is true, I 
suppose there may be other usages of Module.isOpen, including in the JDK, which 
(incorrectly) do not also check if the package name is exported with 
Module.isExported.

The real-world case where I met this issue is in kotlin.stdlib where we store 
metadata of Kotlin declarations in resource files per package (only of those 
declarations which are not representable by JVM class files), and 
kotlin.reflect (which is another module) reaches out to those resource files in 
kotlin.stdlib. To make them reachable thus along with every "exports XXX" in 
kotlin.stdlib's module declaration I'm adding "opens XXX to kotlin.reflect", 
which looks cumbersome.

Thanks!

Alexander

Reply via email to