Hi, While working on modularization of my application I've noticed encapsulation rules for non-class-file resources are different depending on the resource directory names.
It was not quite obvious for me and my colleagues even though it is a part of the spec. I wonder if this can be possibly clarified in the documentation. Please see an example below. The specification for [getResourceAsStream][1] says that the resource is encapsulated if a *package name* is derived from its name. So if the [resource’s directory name is NOT a valid Java identifier][2], it is NOT encapsulated. Which means that if a module has a resource located under, for example, a directory named `dir-3` (containing a non-valid character `-` in its name) it will always be accessible from outside of the module. Here is an example of two Java modules ([source code in GitHub][3]). *Module 1* consists of the following resource files: ├── dir-3 │ └── resource3.txt ├── dir1 │ └── resource1.txt ├── dir2 │ └── resource2.txt └── root.txt and `module-info.java`: module module_one { opens dir1; } *Module 2* requires *Module 1* in `module-info.java`: module module_two { requires module_one; } and has a sample main class for loading various resource files: package module2; import java.io.IOException; public class Main { public static void main(String[] args) throws IOException { loadResource("root.txt", "From module's root directory"); loadResource("dir1/resource1.txt", "From opened package `dir1`"); loadResource("dir2/resource2.txt", "From internal package `dir2`"); loadResource("dir-3/resource3.txt", "From directory `dir-3` with non-Java name"); } public static void loadResource(String name, String comment) throws IOException { // module2 application class loader final var classLoader = Main.class.getClassLoader(); try (var in = classLoader.getResourceAsStream(name)) { System.out.println(); System.out.println("// " + comment); System.out.println(name + ": " + (in != null)); } } } Running the code above gives the following output: // From module's root directory root.txt: true // From opened package `dir1` dir1/resource1.txt: true // From internal package `dir2` dir2/resource2.txt: false // From directory `dir-3` with non-Java name dir-3/resource3.txt: true As you can see the resource file from the root directory and from the `dir-3` directory are not encapsulated, therefore *Module 2* can load them. The package `dir1` is encapsulated but unconditionally opened. *Module 2* can load it as well. The package `dir2` is encapsulated and not opened. *Module 2* cannot load it. Note that *Module 2* cannot contain its own resources under `dir1` and `dir2` directories because they are already encapsulated in *Module 1*. If you try adding `dir1` you will get the following error: Error occurred during initialization of boot layer java.lang.LayerInstantiationException: Package dir1 in both module module_one and module module_two Regards, Alexey [1]: https://docs.oracle.com/javase/9/docs/api/java/lang/Module.html#getResourceAsStream-java.lang.String- [2]: https://docs.oracle.com/javase/8/docs/technotes/guides/lang/resources.html [3]: https://github.com/agavrilov76/jpms-resource