Update: I answered my own question here:
Scanning classpath/modulepath in runtime in Java 9
--
[Old question -- obsolete:]
What is the correct way to get a ModuleReference
given only a Module
object in Java 9?
Consider these two methods of referring to java.base
:
Module mod = ModuleLayer.boot().findModule("java.base").orElse(null);
ModuleReference modRef = ModuleFinder.ofSystem().find("java.base").orElse(null);
mod
has a method Set<String> getPackages()
, but you only get the names of the packages, you cannot list the resources in each package.
modRef
has a method ModuleReader open()
, and ModuleReader
has a method Stream<String> list()
that lists the resources in the module, which is what I need to do.
However, for automatic (and therefore unnamed) modules, produced by adding non-module jarfiles to the classpath, you cannot get a ModuleReference
from ModuleFinder.ofSystem().find(String name)
or ModuleFinder.ofSystem().findAll()
-- you can only get the Module
reference from getClass().getModule()
.
I cannot find any way to get a ModuleReference
for automatic modules. I also cannot find a way to get a ModuleReference
from a Module
object, which means I am not able to list the resources in a Module
if the module is automatic and/or unnamed.
Surely there must be a way to get a ModuleReference
for a given (already-loaded) Module
?
An unnamed module is a JAR that is built without module-info. java declaration. An unnamed module will require all other modules and will export all its packages as well. Type 2: Named Module. A named module is a module that is created with a module declaration file module-info.
Java Module System is a major change in Java 9 version. Java added this feature to collect Java packages and code into a single unit called module. In earlier versions of Java, there was no concept of module to create modular Java applications, that why size of application increased and difficult to move around.
Project Jigsaw is an umbrella project with the new features aimed at two aspects: the introduction of module system in the Java language. and its implementation in JDK source and Java runtime.
First thing to clear out from the question is that the inference is incorrect in the sentence -
for automatic (and therefore unnamed) modules, produced by adding non-module jar files to the classpath
Automatic modules are named modules found on the module path. On the other hand, the unnamed module is a member of the module system which supports loading a type from the classpath whose package is not defined in any known(named) module.
The ClassLoader
that was used to load the type itself can be used to get the Module
(unnamed). I've tried explaining this in the answer to How many unnamed modules are created in Java 9? as well. To link to the precise documentation over the same that also answers with which class loader is the unnamed module associated?
Every class loader, it turns out, has its own unique unnamed module, which is returned by the new
ClassLoader::getUnnamedModule
method....
ClassLoader cl = getClass().getClassLoader();// returns the class loader for the class
Module yourClassLoaderUnnamedModule = cl.getUnnamedModule();
Moving further the document adds to getting the module of a type loaded form unnamed module::
.. type is considered to be in that loader’s unnamed module, i.e., the
getModule
method of the type’s Class object will return its loader’s unnamed module.
which eventually is equivalent to :
Module yourClassUnnamedModule = getClass().getModule(); // from the type itself
Primarily in terms of accessing resources of the unnamed module, though I agree there is no API currently visible to access the unnamed module's resources etc. Yet, since the type of the Class objects loaded via this module would always be from the classpath, one can either get all the resources of the classpath that is in use or the other way around, you can check if the resource in use is accessed from classpath or the module path. One way I could think of is to verify using the above two functionalities as :
yourClassLoaderUnnamedModule.equals(yourClassUnnamedModule)//true if resource is loaded via classpath
The module finder returned by ModuleFinder.ofSystem()
is one that locates system modules, which are the modules built into the JRE environment running the application.
If the location of the automatic module on the file system is known, you could try retrieving a module finder using the directory, i.e. using ModuleFinder.of(path)
. Another way is to use the module layer’s configuration to resolve the module reference:
Optional<ResolvedModule> resolvedModule = ModuleLayer.boot().configuration().findModule(name);
Optional<ModuleReference> moduleReference = resolvedModule.map(ResolvedModule::reference);
To answer your general question about obtaining a module reference from only a Module
, one way to do it:
Optional<ModuleReference> moduleReference
= module.getLayer().configuration()
.findModule(module.getName())
.map(ResolvedModule::reference);
For an unnamed module, my guess is that you cannot retrieve a ModuleReference
for it, but at least one can try calling configuration().modules()
and see if they include an unnamed module.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With