Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get a Java 9 ModuleReference for an unnamed module [duplicate]

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?

like image 610
Luke Hutchison Avatar asked Dec 24 '17 08:12

Luke Hutchison


People also ask

What is unnamed module in Java?

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.

What is modularity java9?

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.

What is Java jigsaw?

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.


2 Answers

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
like image 154
Naman Avatar answered Oct 13 '22 15:10

Naman


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.

like image 21
M A Avatar answered Oct 13 '22 16:10

M A