Exporting all modules to all modules at runtime on Java 16 and later
Tags: java, reflection, tutorial
Published: 2021-09-18 21:31:06

From Java 9 is not allowed by default an application to see all classes from the JDK, unlike all previous versions of Java, due to the new module system. So if we try to access some reserved module we obtain an error like this:
`module <module-name> does not "opens <package-name>" to unnamed module`.
Everyone knows that we can solve this exception by using the JVM parameters `--add-exports` or `add-opens`, but how we can do for example if we have more environments and we don't want to have to change JVM args across these environments?
In this situation [**Burningwave Core**](https://burningwave.github.io/core/) comes to our aid by providing us with the method `org.burningwave.core.assembler.StaticComponentContainer.Modules.exportAllToAll()` that allows us to export all modules in all modules, thus solving our problem.
To include this library in our project we need to add the following dependency to our _pom.xml_:

{% gist https://gist.github.com/Roberto-Gentili/536ee2d3f775030d46d82a008da10dbe.js %}

The method `org.burningwave.core.assembler.StaticComponentContainer.Modules.exportAllToAll()` **is called by default on the initialization of the class** `org.burningwave.core.assembler.StaticComponentContainer` but this behavior can be changed by including in the base folder of your class path a file named [`burningwave.static.properties`](https://github.com/burningwave/core#configuration) that contains a [property named `modules.export-all-to-all` whose value is false](https://github.com/JJBRT/advanced-java-tutorials/blob/master/reflection/src/main/java/burningwave.static.properties) thus leaving us the possibility to call this method manually (**note that it is not necessary to put in the `burningwave.static.properties` file all the properties present in the relative link supplied before**):
```java
org.burningwave.core.assembler.StaticComponentContainer.Modules.exportAllToAll();
//Now that we have called exportAllToAll () we can use any class of any module
Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
method.setAccessible(true);
ClassLoader classLoader = new URLClassLoader(new URL[] {}, null);
method.invoke(
	classLoader,
	org.burningwave.core.assembler.StaticComponentContainer.Resources.getClassPath(AllModulesToAllModulesExporter.class).getURL()
);
Class<?> fieldsHandlerClass = classLoader.loadClass(FieldsHandler.class.getName());
if (FieldsHandler.class != fieldsHandlerClass) {
	System.out.println(
		FieldsHandler.class.toString() + " and " + fieldsHandlerClass.toString() + " are loaded from the same bytecode but they are different instances:" +
		"\n\t" + FieldsHandler.class + " is loaded by " + FieldsHandler.class.getClassLoader() +
		"\n\t" + fieldsHandlerClass + " is loaded by " + fieldsHandlerClass.getClassLoader()
	);
}
```

The Modules component also **exposes other methods for greater granularity**:
* `export(String moduleNameFrom, String moduleNameTo)`
* `exportPackage(String moduleNameFrom, String moduleNameTo, String... packageNames)`
* `exportPackageToAll(String name, String... packageNames)`
* `exportPackageToAllUnnamed(String name, String... packageNames)`
* `exportToAll(String name)`
* `exportToAllUnnamed(String name)`

Therefore, referring to the example above, if we want to limit the export to the package of our interest we have just to replace the call `exportAllToAll()` with `exportPackageToAllUnnamed("java.base", "java.net")`.

[**From here**](https://github.com/JJBRT/advanced-java-tutorials) you can download/clone the [**tutorial shared on GitHub**](https://github.com/JJBRT/advanced-java-tutorials/tree/master/reflection) that contains [another example](https://github.com/JJBRT/advanced-java-tutorials/blob/master/reflection/src/main/java/com/github/jjbrt/reflection/AllModulesToAllModulesExporter.java) about to use the method `org.burningwave.core.assembler.StaticComponentContainer.Modules.exportAllToAll()`.